| 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 | diff --git a/dbe/dbe.c b/dbe/dbe.c |
| 27 | index 527588c..df2ad5c 100644 |
| 28 | --- a/dbe/dbe.c |
| 29 | +++ b/dbe/dbe.c |
| 30 | @@ -450,18 +450,20 @@ ProcDbeSwapBuffers(ClientPtr client) |
| 31 | DbeSwapInfoPtr swapInfo; |
| 32 | xDbeSwapInfo *dbeSwapInfo; |
| 33 | int error; |
| 34 | - register int i, j; |
| 35 | - int nStuff; |
| 36 | + unsigned int i, j; |
| 37 | + unsigned int nStuff; |
| 38 | |
| 39 | REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); |
| 40 | nStuff = stuff->n; /* use local variable for performance. */ |
| 41 | |
| 42 | if (nStuff == 0) { |
| 43 | + REQUEST_SIZE_MATCH(xDbeSwapBuffersReq); |
| 44 | return Success; |
| 45 | } |
| 46 | |
| 47 | if (nStuff > UINT32_MAX / sizeof(DbeSwapInfoRec)) |
| 48 | return BadAlloc; |
| 49 | + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, nStuff * sizeof(xDbeSwapInfo)); |
| 50 | |
| 51 | /* Get to the swap info appended to the end of the request. */ |
| 52 | dbeSwapInfo = (xDbeSwapInfo *) &stuff[1]; |
| 53 | @@ -914,13 +916,16 @@ static int |
| 54 | SProcDbeSwapBuffers(ClientPtr client) |
| 55 | { |
| 56 | REQUEST(xDbeSwapBuffersReq); |
| 57 | - register int i; |
| 58 | + unsigned int i; |
| 59 | xDbeSwapInfo *pSwapInfo; |
| 60 | |
| 61 | swaps(&stuff->length); |
| 62 | REQUEST_AT_LEAST_SIZE(xDbeSwapBuffersReq); |
| 63 | |
| 64 | swapl(&stuff->n); |
| 65 | + if (stuff->n > UINT32_MAX / sizeof(DbeSwapInfoRec)) |
| 66 | + return BadAlloc; |
| 67 | + REQUEST_FIXED_SIZE(xDbeSwapBuffersReq, stuff->n * sizeof(xDbeSwapInfo)); |
| 68 | |
| 69 | if (stuff->n != 0) { |
| 70 | pSwapInfo = (xDbeSwapInfo *) stuff + 1; |
| 71 | -- |
| 72 | 1.7.9.2 |
| 73 | |