| 1 | From 0d50f11aa10fe64c74ab7b3c572cc2f3ff583020 Mon Sep 17 00:00:00 2001 |
| 2 | From: Alan Coopersmith <alan.coopersmith@oracle.com> |
| 3 | Date: Wed, 22 Jan 2014 23:12:04 -0800 |
| 4 | Subject: [PATCH 07/33] dbe: unvalidated lengths in DbeSwapBuffers calls |
| 5 | [CVE-2014-8097] |
| 6 | |
| 7 | ProcDbeSwapBuffers() has a 32bit (n) length value that it uses to read |
| 8 | from a buffer. The length is never validated, which can lead to out of |
| 9 | bound reads, and possibly returning the data read from out of bounds to |
| 10 | the misbehaving client via an X Error packet. |
| 11 | |
| 12 | SProcDbeSwapBuffers() swaps data (for correct endianness) before |
| 13 | handing it off to the real proc. While doing the swapping, the |
| 14 | length field is not validated, which can cause memory corruption. |
| 15 | |
| 16 | v2: reorder checks to avoid compilers optimizing out checks for overflow |
| 17 | that happen after we'd already have done the overflowing multiplications. |
| 18 | |
| 19 | Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com> |
| 20 | Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> |
| 21 | Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> |
| 22 | --- |
| 23 | dbe/dbe.c | 11 ++++++++--- |
| 24 | 1 file changed, 8 insertions(+), 3 deletions(-) |
| 25 | |
| 26 | --- a/dbe/dbe.c |
| 27 | +++ b/dbe/dbe.c |
| 28 | @@ -450,18 +450,20 @@ ProcDbeSwapBuffers(ClientPtr client) |
| 29 | DbeSwapInfoPtr swapInfo; |
| 30 | xDbeSwapInfo *dbeSwapInfo; |
| 31 | int error; |
| 32 | - register int i, j; |
| 33 | - int nStuff; |
| 34 | + unsigned int i, j; |
| 35 | + unsigned int nStuff; |
| 36 | |
| 37 | REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); |
| 38 | nStuff = stuff->n; /* use local variable for performance. */ |
| 39 | |
| 40 | if (nStuff == 0) { |
| 41 | + REQUEST_SIZE_MATCH(xDbeSwapBuffersReq); |
| 42 | return Success; |
| 43 | } |
| 44 | |
| 45 | if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) |
| 46 | return BadAlloc; |
| 47 | + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo)); |
| 48 | |
| 49 | /* Get to the swap info appended to the end of the request. */ |
| 50 | dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; |
| 51 | @@ -914,13 +916,16 @@ static int |
| 52 | SProcDbeSwapBuffers(ClientPtr client) |
| 53 | { |
| 54 | REQUEST(xDbeSwapBuffersReq); |
| 55 | - register int i; |
| 56 | + unsigned int i; |
| 57 | xDbeSwapInfo *pSwapInfo; |
| 58 | |
| 59 | swaps(&stuff->length); |
| 60 | REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); |
| 61 | |
| 62 | swapl(&stuff->n); |
| 63 | + if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec)) |
| 64 | + return BadAlloc; |
| 65 | + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo)); |
| 66 | |
| 67 | if (stuff->n != 0) { |
| 68 | pSwapInfo = (xDbeSwapInfo *) stuff + 1; |