[Xcb] XGE malloc bug - too small due to xcb struct padding
Mark Kettenis
mark.kettenis at xs4all.nl
Sun Dec 29 07:03:02 PST 2013
> Date: Sun, 29 Dec 2013 01:03:31 -0800
> From: Josh Triplett <josh at joshtriplett.org>
>
> On Sun, Dec 29, 2013 at 12:54:10AM -0800, Kenneth Graunke wrote:
> > Hello,
> >
> > I believe I've found a bug in libxcb's read_packet() function where, for
> > XGE events larger than 32-bytes, the size of the malloc'd buffer may be
> > too small.
> >
> > Specifically, I'm looking at the PresentCompleteNotify event:
> >
> > (gdb) ptype xcb_present_complete_notify_event_t
> > type = struct xcb_present_complete_notify_event_t {
> > uint8_t response_type;
> > uint8_t extension;
> > uint16_t sequence;
> > uint32_t length;
> > uint16_t event_type;
> > uint8_t kind;
> > uint8_t mode;
> > xcb_present_event_t event;
> > xcb_window_t window;
> > uint32_t serial;
> > uint64_t ust;
> > uint32_t full_sequence;
> > uint64_t msc;
> > }
> >
> > Note that XCB's structure doesn't match the X protocol due to the extra
> > uint32_t full_sequence field, right at the 32 byte boundary.
> >
> > When allocating the XCB struct, it looks like read_packet() adds an
> > extra sizeof(uint32_t) to accommodate this extra field:
> >
> > bufsize = length + eventlength + nfd * sizeof(int) +
> > (genrep.response_type == XCB_REPLY ? 0 : sizeof(uint32_t));
> > ^^^^^^^^^^^^^^^^
> >
> > However, this appears to be insufficient. In this case, the
> > PresentCompleteNotify event is 40 bytes on the wire, while the XCB
> > struct is actually *48 bytes*, due to extra padding:
> >
> > (gdb) p (int) &((xcb_present_complete_notify_event_t *) 0)->full_sequence
> > $1 = 32
> > (gdb) p (int) &((xcb_present_complete_notify_event_t *) 0)->msc
> > $2 = 40
> >
> > So we've allocated 44 bytes when we should have allocated 48 bytes.
> > Reading or writing msc results in scribbling off the end of the buffer.
> > ('valgrind glxgears' on a 64-bit system with DRI3 reproduces this.)
> >
> > I'm not sure how best to fix this. The existing code bases the length
> > entirely on the protocol description, but this extra padding doesn't
> > exist on the wire...it's purely in XCB's structures. Any ideas?
>
> I don't think XCB is taking that padding into account when copying the
> pieces of the structure around to accomodate the full_sequence field,
> either. The right answer is probably to mark the structure as packed.
That isn't the right answer. The 64-bit fields will be misaligned and
accessing them on a strict alignment architecture will trigger a bus
error.
Looks like the logic for inserting the extra "full_sequence" field is
busted. To support 64-bit fields in the "extended part" of the event,
we need 32 bits of padding after the "full_sequence" member. That
padding also needs to be added to xcb_generic_event_t to make sure
that xcb_in.c:read_packet() puts the XGE event data in the right spot.
More information about the Xcb
mailing list