From 2ef42519c41e793579c9cea699c866fee3d9321f Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 22 Jan 2014 23:12:04 -0800 Subject: dbe: unvalidated lengths in DbeSwapBuffers calls [CVE-2014-8097] ProcDbeSwapBuffers() has a 32bit (n) length value that it uses to read from a buffer. The length is never validated, which can lead to out of bound reads, and possibly returning the data read from out of bounds to the misbehaving client via an X Error packet. SProcDbeSwapBuffers() swaps data (for correct endianness) before handing it off to the real proc. While doing the swapping, the length field is not validated, which can cause memory corruption. v2: reorder checks to avoid compilers optimizing out checks for overflow that happen after we'd already have done the overflowing multiplications. Reported-by: Ilja Van Sprundel Signed-off-by: Alan Coopersmith Reviewed-by: Peter Hutterer --- dbe/dbe.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'dbe') diff --git a/dbe/dbe.c b/dbe/dbe.c index 527588c3c..df2ad5c51 100644 --- a/dbe/dbe.c +++ b/dbe/dbe.c @@ -450,18 +450,20 @@ ProcDbeSwapBuffers(ClientPtr client) DbeSwapInfoPtr swapInfo; xDbeSwapInfo *dbeSwapInfo; int error; - register int i, j; - int nStuff; + unsigned int i, j; + unsigned int nStuff; REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); nStuff = stuff->n; /* use local variable for performance. */ if (nStuff == 0) { + REQUEST_SIZE_MATCH(xDbeSwapBuffersReq); return Success; } if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) return BadAlloc; + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo)); /* Get to the swap info appended to the end of the request. */ dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; @@ -914,13 +916,16 @@ static int SProcDbeSwapBuffers(ClientPtr client) { REQUEST(xDbeSwapBuffersReq); - register int i; + unsigned int i; xDbeSwapInfo *pSwapInfo; swaps(&stuff->length); REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); swapl(&stuff->n); + if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec)) + return BadAlloc; + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo)); if (stuff->n != 0) { pSwapInfo = (xDbeSwapInfo *) stuff + 1; -- cgit v1.2.3