Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 05 Sep 2017 12:28:43 +0000
From:      bugzilla-noreply@freebsd.org
To:        freebsd-bugs@FreeBSD.org
Subject:   [Bug 222066] mpt crash in virtualbox
Message-ID:  <bug-222066-8@https.bugs.freebsd.org/bugzilla/>

next in thread | raw e-mail | index | archive | help
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=3D222066

            Bug ID: 222066
           Summary: mpt crash in virtualbox
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: freebsd-bugs@FreeBSD.org
          Reporter: avg@FreeBSD.org

We are seeing a kernel crash in mpt driver while running FreeBSD as a guest=
 in
Virtualbox.

The problem seems to be caused by Virtualbox setting the request frame size
parameter to 512 bytes:

pReply->IOCFacts.u16RequestFrameSize  =3D 128;    /* @todo Figure out where=
 it is
needed. */

The driver does not seem to be able to cope with such a large frame size.
It could be argued that the bug is on the Virtualbox side.  I am not sure i=
f it
really needs such a size (especially, given the comment).

Anyway, it could be useful to be able to handle that value in mpt.

A bit of code analysis follows.
In the code we have the following important definitions:

/* MPT_RQSL- size of request frame, in bytes */
#define MPT_RQSL(mpt)           (mpt->ioc_facts.RequestFrameSize << 2)

#define MPT_MAX_REQUESTS(mpt)   512
#define MPT_REQUEST_AREA        512
#define MPT_SENSE_SIZE          32      /* included in MPT_REQUEST_AREA */
#define MPT_REQ_MEM_SIZE(mpt)   (MPT_MAX_REQUESTS(mpt) * MPT_REQUEST_AREA)

So, the code allocates 512 request buffers of 512 bytes each as a single
contiguous (both physically and virtually) buffer suitable for DMA between =
the
driver and the hardware (see mpt_dma_buf_alloc).

When the crash happens, it's a page fault here:
memcpy <=3D mpt_read_cfg_page <=3D mpt_action

The problematic request:
(kgdb) p *req
$1 =3D {links =3D {tqe_next =3D 0xfffffe000179c390, tqe_prev =3D 0xfffffe00=
01798438},
state =3D 10, index =3D 511, IOCStatus =3D 0, ResponseCode =3D 0,
  serno =3D 37161, ccb =3D 0x0, req_vbuf =3D 0xfffffe0000286e00, sense_vbuf=
 =3D
0xfffffe0000286fe0, req_pbuf =3D 2089315840, sense_pbuf =3D 2089316320,
  dmap =3D 0x0, chain =3D 0x0, callout =3D {c_links =3D {le =3D {le_next =
=3D 0x0, le_prev =3D
0xfffffe0001522df8}, sle =3D {sle_next =3D 0x0}, tqe =3D {
        tqe_next =3D 0x0, tqe_prev =3D 0xfffffe0001522df8}}, c_time =3D
3787081006447, c_precision =3D 1342177187, c_arg =3D 0xfffff80038870000,
    c_func =3D 0xffffffff804a4c30 <mpt_timeout>, c_lock =3D 0xfffffe0001798=
008,
c_flags =3D 0, c_iflags =3D 0, c_cpu =3D 0}}


We see that index is 511, so this is the last request object with its buffe=
r in
the last 512 bytes of the contiguous buffer.
We see that the page fault happens right beyond the allocated buffer region.

So, my interpretation is that RequestFrameSize that's reported by the
[emulated] hardware is too large to be handled by the hardcoded request buf=
fer
size.  The problem is masked for all buffers but the last, because the hard=
ware
would simply overwrite the next request buffer and the driver would read fr=
om
it.  So, no page fault although there is a chance of silent data corruption.
For the last buffer there is obviously no next buffer and we get the page
fault.

Conclusions:
- first of all, the driver should check MPT_RQSL against MPT_REQUEST_AREA a=
nd
refuse to attach if the request frame size is too large
- we can consider bumping MPT_REQUEST_AREA to, e.g., 1024... probably bette=
r to
check
- Linux driver seems to cap the request size at 128 bytes:
=20
http://elixir.free-electrons.com/linux/latest/source/drivers/message/fusion=
/mptbase.c#L3214

--=20
You are receiving this mail because:
You are the assignee for the bug.=



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?bug-222066-8>