[PATCH] libX11: check size of GetReqExtra after XFlush
Jamey Sharp
jamey at minilop.net
Mon Jul 18 10:06:24 PDT 2011
I have a few comments, I guess.
- The indentation in the GetReqExtra definition didn't work out. Looks
like it should be tabs and tabs only, there.
- This patch turns a buffer overrun into a null-pointer dereference if
there's any caller that hasn't been updated. (While you've hit all the
cases I can find in X.Org sources, keep in mind that there are
closed-source Xlib extensions out there.) I think that's an
improvement, but it's worth calling out in the commit message.
- I guess this new behavior should be documented in
specs/libX11/AppC.xml.
- Your mention of 16K in the commit message confused me because I wasn't
sure where you were getting that limit from. Note that Xlib's buffer
size is actually runtime-configurable, down to a minimum of 2K. Could
you explain it in terms of Xlib's output buffer size, please?
- Changing the implementation of GetReqExtra and the rest of Xlibint.h
is only acceptable if code compiled using the old implementation is
ABI compatible with code compiled using the new implementation. I
believe you're good on that count, but I wanted to point it out.
On the whole, I believe this is an improvement. With the above
corrections, I'd be happy to commit this.
Jamey
On Mon, Jul 18, 2011 at 08:57:44AM -0700, Kees Cook wrote:
> Hi, any comments on this? Seems like kind of a nasty surprise bug...
>
> Thanks,
>
> -Kees
>
> On Sat, Jul 09, 2011 at 12:42:57PM -0700, Kees Cook wrote:
> > Two users of GetReqExtra pass arbitrarily sized allocations from the
> > caller (ModMap and Host). Adjust the GetReqExtra macro to double-check
> > the requested length and invalidate "req" when this happens. Users of
> > potentially >16K lengths in GetReqExtra now check "req" and fail if
> > something has gone wrong.
> >
> > https://bugs.launchpad.net/ubuntu/+source/x11-xserver-utils/+bug/792628
> >
> > Signed-off-by: Kees Cook <kees.cook at canonical.com>
> > ---
> > include/X11/Xlibint.h | 28 ++++++++++++++++++----------
> > src/Host.c | 8 ++++++++
> > src/ModMap.c | 4 ++++
> > 3 files changed, 30 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/X11/Xlibint.h b/include/X11/Xlibint.h
> > index 2ce356d..81f8cfd 100644
> > --- a/include/X11/Xlibint.h
> > +++ b/include/X11/Xlibint.h
> > @@ -461,21 +461,29 @@ extern LockInfoPtr _Xglobal_lock;
> > WORD64ALIGN\
> > if ((dpy->bufptr + SIZEOF(x##name##Req) + n) > dpy->bufmax)\
> > _XFlush(dpy);\
> > - req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
> > - req->reqType = X_##name;\
> > - req->length = (SIZEOF(x##name##Req) + n)>>2;\
> > - dpy->bufptr += SIZEOF(x##name##Req) + n;\
> > - dpy->request++
> > + if ((dpy->bufptr + SIZEOF(x##name##Req) + n) <= dpy->bufmax) {\
> > + req = (x##name##Req *)(dpy->last_req = dpy->bufptr);\
> > + req->reqType = X_##name;\
> > + req->length = (SIZEOF(x##name##Req) + n)>>2;\
> > + dpy->bufptr += SIZEOF(x##name##Req) + n;\
> > + dpy->request++;\
> > + } else {\
> > + req = NULL;\
> > + }
> > #else
> > #define GetReqExtra(name, n, req) \
> > WORD64ALIGN\
> > if ((dpy->bufptr + SIZEOF(x/**/name/**/Req) + n) > dpy->bufmax)\
> > _XFlush(dpy);\
> > - req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
> > - req->reqType = X_/**/name;\
> > - req->length = (SIZEOF(x/**/name/**/Req) + n)>>2;\
> > - dpy->bufptr += SIZEOF(x/**/name/**/Req) + n;\
> > - dpy->request++
> > + if ((dpy->bufptr + SIZEOF(x/**/name/**/Req) + n) <= dpy->bufmax) {\
> > + req = (x/**/name/**/Req *)(dpy->last_req = dpy->bufptr);\
> > + req->reqType = X_/**/name;\
> > + req->length = (SIZEOF(x/**/name/**/Req) + n)>>2;\
> > + dpy->bufptr += SIZEOF(x/**/name/**/Req) + n;\
> > + dpy->request++;\
> > + } else {\
> > + req = NULL;\
> > + }
> > #endif
> >
> >
> > diff --git a/src/Host.c b/src/Host.c
> > index da9923a..3f87731 100644
> > --- a/src/Host.c
> > +++ b/src/Host.c
> > @@ -83,6 +83,10 @@ XAddHost (
> >
> > LockDisplay(dpy);
> > GetReqExtra (ChangeHosts, length, req);
> > + if (!req) {
> > + UnlockDisplay(dpy);
> > + return 0;
> > + }
> > req->mode = HostInsert;
> > req->hostFamily = host->family;
> > req->hostLength = addrlen;
> > @@ -118,6 +122,10 @@ XRemoveHost (
> >
> > LockDisplay(dpy);
> > GetReqExtra (ChangeHosts, length, req);
> > + if (!req) {
> > + UnlockDisplay(dpy);
> > + return 0;
> > + }
> > req->mode = HostDelete;
> > req->hostFamily = host->family;
> > req->hostLength = addrlen;
> > diff --git a/src/ModMap.c b/src/ModMap.c
> > index c99bfdd..5deb894 100644
> > --- a/src/ModMap.c
> > +++ b/src/ModMap.c
> > @@ -75,6 +75,10 @@ XSetModifierMapping(
> >
> > LockDisplay(dpy);
> > GetReqExtra(SetModifierMapping, mapSize, req);
> > + if (!req) {
> > + UnlockDisplay(dpy);
> > + return 2;
> > + }
> >
> > req->numKeyPerModifier = modifier_map->max_keypermod;
> >
> > --
> > 1.7.4.1
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://lists.x.org/archives/xorg-devel/attachments/20110718/c7087c71/attachment.pgp>
More information about the xorg-devel
mailing list