|
1 From bb82c72a1d69eaf60b7586570faf797df967f661 Mon Sep 17 00:00:00 2001 |
|
2 From: Alan Coopersmith <[email protected]> |
|
3 Date: Mon, 29 Apr 2013 18:39:34 -0700 |
|
4 Subject: [PATCH:libXi] Expand comment on the memory vs. reply ordering in |
|
5 XIGetSelectedEvents() |
|
6 |
|
7 Unpacking from the wire involves un-interleaving the structs & masks, |
|
8 which wasn't obvious to me the first time I read it, so make notes |
|
9 before I forget again. |
|
10 |
|
11 Signed-off-by: Alan Coopersmith <[email protected]> |
|
12 Signed-off-by: Peter Hutterer <[email protected]> |
|
13 --- |
|
14 src/XISelEv.c | 10 ++++++++-- |
|
15 1 file changed, 8 insertions(+), 2 deletions(-) |
|
16 |
|
17 diff --git a/src/XISelEv.c b/src/XISelEv.c |
|
18 index fa7eb54..f871222 100644 |
|
19 --- a/src/XISelEv.c |
|
20 +++ b/src/XISelEv.c |
|
21 @@ -135,8 +135,14 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) |
|
22 |
|
23 _XRead(dpy, (char*)mask_in, reply.length * 4); |
|
24 |
|
25 - /* Memory layout of the XIEventMask for a 3 mask reply: |
|
26 - * [struct a][struct b][struct c][masks a][masks b][masks c] |
|
27 + /* |
|
28 + * This function takes interleaved xXIEventMask structs & masks off |
|
29 + * the wire, such as this 3 mask reply: |
|
30 + * [struct a][masks a][struct b][masks b][struct c][masks c] |
|
31 + * And generates a memory buffer to be returned to callers in which |
|
32 + * they are not interleaved, so that callers can treat the returned |
|
33 + * pointer as a simple array of XIEventMask structs, such as: |
|
34 + * [struct a][struct b][struct c][masks a][masks b][masks c] |
|
35 */ |
|
36 len = reply.num_masks * sizeof(XIEventMask); |
|
37 |
|
38 -- |
|
39 1.7.9.2 |
|
40 |
|
41 From 63841a81a340f1979cf5b0ffa1f7047dca988994 Mon Sep 17 00:00:00 2001 |
|
42 From: Alan Coopersmith <[email protected]> |
|
43 Date: Wed, 1 May 2013 23:58:39 -0700 |
|
44 Subject: [PATCH:libXi 01/13] Use _XEatDataWords to avoid overflow of |
|
45 rep.length bit shifting |
|
46 |
|
47 rep.length is a CARD32, so rep.length << 2 could overflow in 32-bit builds |
|
48 |
|
49 Signed-off-by: Alan Coopersmith <[email protected]> |
|
50 Reviewed-by: Peter Hutterer <[email protected]> |
|
51 --- |
|
52 configure.ac | 6 ++++++ |
|
53 src/XGMotion.c | 2 +- |
|
54 src/XGetDCtl.c | 2 +- |
|
55 src/XGetDProp.c | 5 ++--- |
|
56 src/XGetFCtl.c | 2 +- |
|
57 src/XGetKMap.c | 2 +- |
|
58 src/XGetMMap.c | 2 +- |
|
59 src/XGetProp.c | 4 +--- |
|
60 src/XGtSelect.c | 2 +- |
|
61 src/XIProperties.c | 7 +++---- |
|
62 src/XIint.h | 14 ++++++++++++++ |
|
63 src/XListDProp.c | 2 +- |
|
64 src/XListDev.c | 2 +- |
|
65 src/XOpenDev.c | 2 +- |
|
66 src/XQueryDv.c | 2 +- |
|
67 15 files changed, 36 insertions(+), 20 deletions(-) |
|
68 |
|
69 diff --git a/configure.ac b/configure.ac |
|
70 index 8dbca38..f5ef1e2 100644 |
|
71 --- a/configure.ac |
|
72 +++ b/configure.ac |
|
73 @@ -31,6 +31,12 @@ PKG_CHECK_MODULES(XI, [xproto >= 7.0.13] [x11 >= 1.4.99.1] [xextproto >= 7.0.3] |
|
74 # CFLAGS only for PointerBarrier typedef |
|
75 PKG_CHECK_MODULES(XFIXES, [xfixes >= 5]) |
|
76 |
|
77 +# Check for _XEatDataWords function that may be patched into older Xlib releases |
|
78 +SAVE_LIBS="$LIBS" |
|
79 +LIBS="$XI_LIBS" |
|
80 +AC_CHECK_FUNCS([_XEatDataWords]) |
|
81 +LIBS="$SAVE_LIBS" |
|
82 + |
|
83 # Check for xmlto and asciidoc for man page conversion |
|
84 # (only needed by people building tarballs) |
|
85 if test "$have_xmlto" = yes && test "$have_asciidoc" = yes; then |
|
86 diff --git a/src/XGMotion.c b/src/XGMotion.c |
|
87 index 99b1c44..5feac85 100644 |
|
88 --- a/src/XGMotion.c |
|
89 +++ b/src/XGMotion.c |
|
90 @@ -112,7 +112,7 @@ XGetDeviceMotionEvents( |
|
91 Xfree(bufp); |
|
92 Xfree(savp); |
|
93 *nEvents = 0; |
|
94 - _XEatData(dpy, (unsigned long)size); |
|
95 + _XEatDataWords(dpy, rep.length); |
|
96 UnlockDisplay(dpy); |
|
97 SyncHandle(); |
|
98 return (NULL); |
|
99 diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c |
|
100 index c66212d..f73a4e8 100644 |
|
101 --- a/src/XGetDCtl.c |
|
102 +++ b/src/XGetDCtl.c |
|
103 @@ -95,7 +95,7 @@ XGetDeviceControl( |
|
104 nbytes = (long)rep.length << 2; |
|
105 d = (xDeviceState *) Xmalloc((unsigned)nbytes); |
|
106 if (!d) { |
|
107 - _XEatData(dpy, (unsigned long)nbytes); |
|
108 + _XEatDataWords(dpy, rep.length); |
|
109 goto out; |
|
110 } |
|
111 sav = d; |
|
112 diff --git a/src/XGetDProp.c b/src/XGetDProp.c |
|
113 index 5d44f91..f9e8f0c 100644 |
|
114 --- a/src/XGetDProp.c |
|
115 +++ b/src/XGetDProp.c |
|
116 @@ -112,14 +112,13 @@ XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
117 * This part of the code should never be reached. If it is, |
|
118 * the server sent back a property with an invalid format. |
|
119 */ |
|
120 - nbytes = rep.length << 2; |
|
121 - _XEatData(dpy, (unsigned long) nbytes); |
|
122 + _XEatDataWords(dpy, rep.length); |
|
123 UnlockDisplay(dpy); |
|
124 SyncHandle(); |
|
125 return(BadImplementation); |
|
126 } |
|
127 if (! *prop) { |
|
128 - _XEatData(dpy, (unsigned long) nbytes); |
|
129 + _XEatDataWords(dpy, rep.length); |
|
130 UnlockDisplay(dpy); |
|
131 SyncHandle(); |
|
132 return(BadAlloc); |
|
133 diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c |
|
134 index 43afa00..28fab4d 100644 |
|
135 --- a/src/XGetFCtl.c |
|
136 +++ b/src/XGetFCtl.c |
|
137 @@ -95,7 +95,7 @@ XGetFeedbackControl( |
|
138 nbytes = (long)rep.length << 2; |
|
139 f = (xFeedbackState *) Xmalloc((unsigned)nbytes); |
|
140 if (!f) { |
|
141 - _XEatData(dpy, (unsigned long)nbytes); |
|
142 + _XEatDataWords(dpy, rep.length); |
|
143 goto out; |
|
144 } |
|
145 sav = f; |
|
146 diff --git a/src/XGetKMap.c b/src/XGetKMap.c |
|
147 index 9431fbb..00dde06 100644 |
|
148 --- a/src/XGetKMap.c |
|
149 +++ b/src/XGetKMap.c |
|
150 @@ -99,7 +99,7 @@ XGetDeviceKeyMapping(register Display * dpy, XDevice * dev, |
|
151 if (mapping) |
|
152 _XRead(dpy, (char *)mapping, nbytes); |
|
153 else |
|
154 - _XEatData(dpy, (unsigned long)nbytes); |
|
155 + _XEatDataWords(dpy, rep.length); |
|
156 } |
|
157 |
|
158 UnlockDisplay(dpy); |
|
159 diff --git a/src/XGetMMap.c b/src/XGetMMap.c |
|
160 index 8a1cdb2..ce10c2d 100644 |
|
161 --- a/src/XGetMMap.c |
|
162 +++ b/src/XGetMMap.c |
|
163 @@ -92,7 +92,7 @@ XGetDeviceModifierMapping( |
|
164 if (res->modifiermap) |
|
165 _XReadPad(dpy, (char *)res->modifiermap, nbytes); |
|
166 else |
|
167 - _XEatData(dpy, (unsigned long)nbytes); |
|
168 + _XEatDataWords(dpy, rep.length); |
|
169 res->max_keypermod = rep.numKeyPerModifier; |
|
170 } |
|
171 |
|
172 diff --git a/src/XGetProp.c b/src/XGetProp.c |
|
173 index c5d088b..34bc581 100644 |
|
174 --- a/src/XGetProp.c |
|
175 +++ b/src/XGetProp.c |
|
176 @@ -68,7 +68,6 @@ XGetDeviceDontPropagateList( |
|
177 int *count) |
|
178 { |
|
179 XEventClass *list = NULL; |
|
180 - int rlen; |
|
181 xGetDeviceDontPropagateListReq *req; |
|
182 xGetDeviceDontPropagateListReply rep; |
|
183 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
184 @@ -90,7 +89,6 @@ XGetDeviceDontPropagateList( |
|
185 *count = rep.count; |
|
186 |
|
187 if (*count) { |
|
188 - rlen = rep.length << 2; |
|
189 list = (XEventClass *) Xmalloc(rep.length * sizeof(XEventClass)); |
|
190 if (list) { |
|
191 int i; |
|
192 @@ -105,7 +103,7 @@ XGetDeviceDontPropagateList( |
|
193 list[i] = (XEventClass) ec; |
|
194 } |
|
195 } else |
|
196 - _XEatData(dpy, (unsigned long)rlen); |
|
197 + _XEatDataWords(dpy, rep.length); |
|
198 } |
|
199 |
|
200 UnlockDisplay(dpy); |
|
201 diff --git a/src/XGtSelect.c b/src/XGtSelect.c |
|
202 index f890db7..5c0f812 100644 |
|
203 --- a/src/XGtSelect.c |
|
204 +++ b/src/XGtSelect.c |
|
205 @@ -104,7 +104,7 @@ XGetSelectedExtensionEvents( |
|
206 (XEventClass *) Xmalloc(*this_client_count * |
|
207 sizeof(XEventClass)); |
|
208 if (!*this_client_list) { |
|
209 - _XEatData(dpy, (unsigned long)tlen + alen); |
|
210 + _XEatDataWords(dpy, rep.length); |
|
211 UnlockDisplay(dpy); |
|
212 SyncHandle(); |
|
213 return (Success); |
|
214 diff --git a/src/XIProperties.c b/src/XIProperties.c |
|
215 index 83a7a68..5e58fb6 100644 |
|
216 --- a/src/XIProperties.c |
|
217 +++ b/src/XIProperties.c |
|
218 @@ -64,7 +64,7 @@ XIListProperties(Display* dpy, int deviceid, int *num_props_return) |
|
219 props = (Atom*)Xmalloc(rep.num_properties * sizeof(Atom)); |
|
220 if (!props) |
|
221 { |
|
222 - _XEatData(dpy, rep.num_properties << 2); |
|
223 + _XEatDataWords(dpy, rep.length); |
|
224 goto cleanup; |
|
225 } |
|
226 |
|
227 @@ -203,8 +203,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, |
|
228 * This part of the code should never be reached. If it is, |
|
229 * the server sent back a property with an invalid format. |
|
230 */ |
|
231 - nbytes = rep.length << 2; |
|
232 - _XEatData(dpy, nbytes); |
|
233 + _XEatDataWords(dpy, rep.length); |
|
234 UnlockDisplay(dpy); |
|
235 SyncHandle(); |
|
236 return(BadImplementation); |
|
237 @@ -222,7 +221,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, |
|
238 *data = Xmalloc(rbytes); |
|
239 |
|
240 if (!(*data)) { |
|
241 - _XEatData(dpy, nbytes); |
|
242 + _XEatDataWords(dpy, rep.length); |
|
243 UnlockDisplay(dpy); |
|
244 SyncHandle(); |
|
245 return(BadAlloc); |
|
246 diff --git a/src/XIint.h b/src/XIint.h |
|
247 index 571bb23..3ddc3c5 100644 |
|
248 --- a/src/XIint.h |
|
249 +++ b/src/XIint.h |
|
250 @@ -83,4 +83,18 @@ next_block(void **ptr, int size) { |
|
251 return ret; |
|
252 } |
|
253 |
|
254 +#ifndef HAVE__XEATDATAWORDS |
|
255 +#include <X11/Xmd.h> /* for LONG64 on 64-bit platforms */ |
|
256 +#include <limits.h> |
|
257 + |
|
258 +static inline void _XEatDataWords(Display *dpy, unsigned long n) |
|
259 +{ |
|
260 +# ifndef LONG64 |
|
261 + if (n >= (ULONG_MAX >> 2)) |
|
262 + _XIOError(dpy); |
|
263 +# endif |
|
264 + _XEatData (dpy, n << 2); |
|
265 +} |
|
266 +#endif |
|
267 + |
|
268 #endif |
|
269 diff --git a/src/XListDProp.c b/src/XListDProp.c |
|
270 index 8667350..bde6cb5 100644 |
|
271 --- a/src/XListDProp.c |
|
272 +++ b/src/XListDProp.c |
|
273 @@ -65,7 +65,7 @@ XListDeviceProperties(Display* dpy, XDevice* dev, int *nprops_return) |
|
274 props = (Atom*)Xmalloc(rep.nAtoms * sizeof(Atom)); |
|
275 if (!props) |
|
276 { |
|
277 - _XEatData(dpy, rep.nAtoms << 2); |
|
278 + _XEatDataWords(dpy, rep.length); |
|
279 goto cleanup; |
|
280 } |
|
281 |
|
282 diff --git a/src/XListDev.c b/src/XListDev.c |
|
283 index bd6e70a..1fa4747 100644 |
|
284 --- a/src/XListDev.c |
|
285 +++ b/src/XListDev.c |
|
286 @@ -202,7 +202,7 @@ XListInputDevices( |
|
287 list = (xDeviceInfo *) Xmalloc(rlen); |
|
288 slist = list; |
|
289 if (!slist) { |
|
290 - _XEatData(dpy, (unsigned long)rlen); |
|
291 + _XEatDataWords(dpy, rep.length); |
|
292 UnlockDisplay(dpy); |
|
293 SyncHandle(); |
|
294 return (XDeviceInfo *) NULL; |
|
295 diff --git a/src/XOpenDev.c b/src/XOpenDev.c |
|
296 index 74f18ac..e784f8b 100644 |
|
297 --- a/src/XOpenDev.c |
|
298 +++ b/src/XOpenDev.c |
|
299 @@ -101,7 +101,7 @@ XOpenDevice( |
|
300 if (rlen - dlen > 0) |
|
301 _XEatData(dpy, (unsigned long)rlen - dlen); |
|
302 } else |
|
303 - _XEatData(dpy, (unsigned long)rlen); |
|
304 + _XEatDataWords(dpy, rep.length); |
|
305 |
|
306 UnlockDisplay(dpy); |
|
307 SyncHandle(); |
|
308 diff --git a/src/XQueryDv.c b/src/XQueryDv.c |
|
309 index 24d4e4e..69c285b 100644 |
|
310 --- a/src/XQueryDv.c |
|
311 +++ b/src/XQueryDv.c |
|
312 @@ -91,7 +91,7 @@ XQueryDeviceState( |
|
313 if (rlen > 0) { |
|
314 data = Xmalloc(rlen); |
|
315 if (!data) { |
|
316 - _XEatData(dpy, (unsigned long)rlen); |
|
317 + _XEatDataWords(dpy, rep.length); |
|
318 goto out; |
|
319 } |
|
320 _XRead(dpy, data, rlen); |
|
321 -- |
|
322 1.7.9.2 |
|
323 |
|
324 From 0acd07e1c9583e2e7c26c13f8628bde992d9bce5 Mon Sep 17 00:00:00 2001 |
|
325 From: Alan Coopersmith <[email protected]> |
|
326 Date: Sat, 9 Mar 2013 22:26:52 -0800 |
|
327 Subject: [PATCH:libXi 02/13] Stack buffer overflow in |
|
328 XGetDeviceButtonMapping() [CVE-2013-1998 1/3] |
|
329 |
|
330 We copy the entire reply sent by the server into the fixed size |
|
331 mapping[] array on the stack, even if the server says it's a larger |
|
332 size than the mapping array can hold. HULK SMASH STACK! |
|
333 |
|
334 Reported-by: Ilja Van Sprundel <[email protected]> |
|
335 Signed-off-by: Alan Coopersmith <[email protected]> |
|
336 Reviewed-by: Peter Hutterer <[email protected]> |
|
337 --- |
|
338 src/XGetBMap.c | 21 +++++++++++++-------- |
|
339 1 file changed, 13 insertions(+), 8 deletions(-) |
|
340 |
|
341 diff --git a/src/XGetBMap.c b/src/XGetBMap.c |
|
342 index 211c9ca..002daba 100644 |
|
343 --- a/src/XGetBMap.c |
|
344 +++ b/src/XGetBMap.c |
|
345 @@ -60,6 +60,7 @@ SOFTWARE. |
|
346 #include <X11/extensions/XInput.h> |
|
347 #include <X11/extensions/extutil.h> |
|
348 #include "XIint.h" |
|
349 +#include <limits.h> |
|
350 |
|
351 #ifdef MIN /* some systems define this in <sys/param.h> */ |
|
352 #undef MIN |
|
353 @@ -75,7 +76,6 @@ XGetDeviceButtonMapping( |
|
354 { |
|
355 int status = 0; |
|
356 unsigned char mapping[256]; /* known fixed size */ |
|
357 - long nbytes; |
|
358 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
359 |
|
360 register xGetDeviceButtonMappingReq *req; |
|
361 @@ -92,13 +92,18 @@ XGetDeviceButtonMapping( |
|
362 |
|
363 status = _XReply(dpy, (xReply *) & rep, 0, xFalse); |
|
364 if (status == 1) { |
|
365 - nbytes = (long)rep.length << 2; |
|
366 - _XRead(dpy, (char *)mapping, nbytes); |
|
367 - |
|
368 - /* don't return more data than the user asked for. */ |
|
369 - if (rep.nElts) |
|
370 - memcpy((char *)map, (char *)mapping, MIN((int)rep.nElts, nmap)); |
|
371 - status = rep.nElts; |
|
372 + if (rep.length <= (sizeof(mapping) >> 2)) { |
|
373 + unsigned long nbytes = rep.length << 2; |
|
374 + _XRead(dpy, (char *)mapping, nbytes); |
|
375 + |
|
376 + /* don't return more data than the user asked for. */ |
|
377 + if (rep.nElts) |
|
378 + memcpy(map, mapping, MIN((int)rep.nElts, nmap)); |
|
379 + status = rep.nElts; |
|
380 + } else { |
|
381 + _XEatDataWords(dpy, rep.length); |
|
382 + status = 0; |
|
383 + } |
|
384 } else |
|
385 status = 0; |
|
386 UnlockDisplay(dpy); |
|
387 -- |
|
388 1.7.9.2 |
|
389 |
|
390 From 18855aa8c261863c00690b7df1e5ce4660687fb6 Mon Sep 17 00:00:00 2001 |
|
391 From: Alan Coopersmith <[email protected]> |
|
392 Date: Sat, 9 Mar 2013 23:37:23 -0800 |
|
393 Subject: [PATCH:libXi 03/13] memory corruption in _XIPassiveGrabDevice() |
|
394 [CVE-2013-1998 2/3] |
|
395 |
|
396 If the server returned more modifiers than the caller asked for, |
|
397 we'd just keep copying past the end of the array provided by the |
|
398 caller, writing over who-knows-what happened to be there. |
|
399 |
|
400 Signed-off-by: Alan Coopersmith <[email protected]> |
|
401 Reviewed-by: Peter Hutterer <[email protected]> |
|
402 --- |
|
403 src/XIPassiveGrab.c | 2 +- |
|
404 1 file changed, 1 insertion(+), 1 deletion(-) |
|
405 |
|
406 diff --git a/src/XIPassiveGrab.c b/src/XIPassiveGrab.c |
|
407 index ac17c01..53b4084 100644 |
|
408 --- a/src/XIPassiveGrab.c |
|
409 +++ b/src/XIPassiveGrab.c |
|
410 @@ -88,7 +88,7 @@ _XIPassiveGrabDevice(Display* dpy, int deviceid, int grabtype, int detail, |
|
411 return -1; |
|
412 _XRead(dpy, (char*)failed_mods, reply.num_modifiers * sizeof(xXIGrabModifierInfo)); |
|
413 |
|
414 - for (i = 0; i < reply.num_modifiers; i++) |
|
415 + for (i = 0; i < reply.num_modifiers && i < num_modifiers; i++) |
|
416 { |
|
417 modifiers_inout[i].status = failed_mods[i].status; |
|
418 modifiers_inout[i].modifiers = failed_mods[i].modifiers; |
|
419 -- |
|
420 1.7.9.2 |
|
421 |
|
422 From a74690ba880036e01fc39f522b7567daf3746a31 Mon Sep 17 00:00:00 2001 |
|
423 From: Alan Coopersmith <[email protected]> |
|
424 Date: Fri, 26 Apr 2013 22:48:36 -0700 |
|
425 Subject: [PATCH:libXi 04/13] unvalidated lengths in XQueryDeviceState() |
|
426 [CVE-2013-1998 3/3] |
|
427 |
|
428 If the lengths given for each class state in the reply add up to more |
|
429 than the rep.length, we could read past the end of the buffer allocated |
|
430 to hold the data read from the server. |
|
431 |
|
432 Signed-off-by: Alan Coopersmith <[email protected]> |
|
433 Reviewed-by: Peter Hutterer <[email protected]> |
|
434 --- |
|
435 src/XQueryDv.c | 17 ++++++++++++----- |
|
436 1 file changed, 12 insertions(+), 5 deletions(-) |
|
437 |
|
438 diff --git a/src/XQueryDv.c b/src/XQueryDv.c |
|
439 index 69c285b..3836777 100644 |
|
440 --- a/src/XQueryDv.c |
|
441 +++ b/src/XQueryDv.c |
|
442 @@ -59,6 +59,7 @@ SOFTWARE. |
|
443 #include <X11/extensions/XInput.h> |
|
444 #include <X11/extensions/extutil.h> |
|
445 #include "XIint.h" |
|
446 +#include <limits.h> |
|
447 |
|
448 XDeviceState * |
|
449 XQueryDeviceState( |
|
450 @@ -66,8 +67,8 @@ XQueryDeviceState( |
|
451 XDevice *dev) |
|
452 { |
|
453 int i, j; |
|
454 - int rlen; |
|
455 - int size = 0; |
|
456 + unsigned long rlen; |
|
457 + size_t size = 0; |
|
458 xQueryDeviceStateReq *req; |
|
459 xQueryDeviceStateReply rep; |
|
460 XDeviceState *state = NULL; |
|
461 @@ -87,9 +88,11 @@ XQueryDeviceState( |
|
462 if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) |
|
463 goto out; |
|
464 |
|
465 - rlen = rep.length << 2; |
|
466 - if (rlen > 0) { |
|
467 - data = Xmalloc(rlen); |
|
468 + if (rep.length > 0) { |
|
469 + if (rep.length < (INT_MAX >> 2)) { |
|
470 + rlen = (unsigned long) rep.length << 2; |
|
471 + data = Xmalloc(rlen); |
|
472 + } |
|
473 if (!data) { |
|
474 _XEatDataWords(dpy, rep.length); |
|
475 goto out; |
|
476 @@ -97,6 +100,10 @@ XQueryDeviceState( |
|
477 _XRead(dpy, data, rlen); |
|
478 |
|
479 for (i = 0, any = (XInputClass *) data; i < (int)rep.num_classes; i++) { |
|
480 + if (any->length > rlen) |
|
481 + goto out; |
|
482 + rlen -= any->length; |
|
483 + |
|
484 switch (any->class) { |
|
485 case KeyClass: |
|
486 size += sizeof(XKeyState); |
|
487 -- |
|
488 1.7.9.2 |
|
489 |
|
490 From 38b563078ee050086526294f42f9f162be4bf97d Mon Sep 17 00:00:00 2001 |
|
491 From: Alan Coopersmith <[email protected]> |
|
492 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
493 Subject: [PATCH:libXi 05/13] integer overflow in XGetDeviceControl() |
|
494 [CVE-2013-1984 1/8] |
|
495 |
|
496 If the number of valuators reported by the server is large enough that |
|
497 it overflows when multiplied by the size of the appropriate struct, then |
|
498 memory corruption can occur when more bytes are copied from the X server |
|
499 reply than the size of the buffer we allocated to hold them. |
|
500 |
|
501 v2: check that reply size fits inside the data read from the server, so |
|
502 we don't read out of bounds either |
|
503 |
|
504 Reported-by: Ilja Van Sprundel <[email protected]> |
|
505 Signed-off-by: Alan Coopersmith <[email protected]> |
|
506 Reviewed-by: Peter Hutterer <[email protected]> |
|
507 --- |
|
508 src/XGetDCtl.c | 31 ++++++++++++++++++++++++------- |
|
509 1 file changed, 24 insertions(+), 7 deletions(-) |
|
510 |
|
511 diff --git a/src/XGetDCtl.c b/src/XGetDCtl.c |
|
512 index f73a4e8..51ed0ae 100644 |
|
513 --- a/src/XGetDCtl.c |
|
514 +++ b/src/XGetDCtl.c |
|
515 @@ -61,6 +61,7 @@ SOFTWARE. |
|
516 #include <X11/extensions/XInput.h> |
|
517 #include <X11/extensions/extutil.h> |
|
518 #include "XIint.h" |
|
519 +#include <limits.h> |
|
520 |
|
521 XDeviceControl * |
|
522 XGetDeviceControl( |
|
523 @@ -68,8 +69,6 @@ XGetDeviceControl( |
|
524 XDevice *dev, |
|
525 int control) |
|
526 { |
|
527 - int size = 0; |
|
528 - int nbytes, i; |
|
529 XDeviceControl *Device = NULL; |
|
530 XDeviceControl *Sav = NULL; |
|
531 xDeviceState *d = NULL; |
|
532 @@ -92,8 +91,12 @@ XGetDeviceControl( |
|
533 goto out; |
|
534 |
|
535 if (rep.length > 0) { |
|
536 - nbytes = (long)rep.length << 2; |
|
537 - d = (xDeviceState *) Xmalloc((unsigned)nbytes); |
|
538 + unsigned long nbytes; |
|
539 + size_t size = 0; |
|
540 + if (rep.length < (INT_MAX >> 2)) { |
|
541 + nbytes = (unsigned long) rep.length << 2; |
|
542 + d = Xmalloc(nbytes); |
|
543 + } |
|
544 if (!d) { |
|
545 _XEatDataWords(dpy, rep.length); |
|
546 goto out; |
|
547 @@ -111,33 +114,46 @@ XGetDeviceControl( |
|
548 case DEVICE_RESOLUTION: |
|
549 { |
|
550 xDeviceResolutionState *r; |
|
551 + size_t val_size; |
|
552 |
|
553 r = (xDeviceResolutionState *) d; |
|
554 - size += sizeof(XDeviceResolutionState) + |
|
555 - (3 * sizeof(int) * r->num_valuators); |
|
556 + if (r->num_valuators >= (INT_MAX / (3 * sizeof(int)))) |
|
557 + goto out; |
|
558 + val_size = 3 * sizeof(int) * r->num_valuators; |
|
559 + if ((sizeof(xDeviceResolutionState) + val_size) > nbytes) |
|
560 + goto out; |
|
561 + size += sizeof(XDeviceResolutionState) + val_size; |
|
562 break; |
|
563 } |
|
564 case DEVICE_ABS_CALIB: |
|
565 { |
|
566 + if (sizeof(xDeviceAbsCalibState) > nbytes) |
|
567 + goto out; |
|
568 size += sizeof(XDeviceAbsCalibState); |
|
569 break; |
|
570 } |
|
571 case DEVICE_ABS_AREA: |
|
572 { |
|
573 + if (sizeof(xDeviceAbsAreaState) > nbytes) |
|
574 + goto out; |
|
575 size += sizeof(XDeviceAbsAreaState); |
|
576 break; |
|
577 } |
|
578 case DEVICE_CORE: |
|
579 { |
|
580 + if (sizeof(xDeviceCoreState) > nbytes) |
|
581 + goto out; |
|
582 size += sizeof(XDeviceCoreState); |
|
583 break; |
|
584 } |
|
585 default: |
|
586 + if (d->length > nbytes) |
|
587 + goto out; |
|
588 size += d->length; |
|
589 break; |
|
590 } |
|
591 |
|
592 - Device = (XDeviceControl *) Xmalloc((unsigned)size); |
|
593 + Device = Xmalloc(size); |
|
594 if (!Device) |
|
595 goto out; |
|
596 |
|
597 @@ -150,6 +166,7 @@ XGetDeviceControl( |
|
598 int *iptr, *iptr2; |
|
599 xDeviceResolutionState *r; |
|
600 XDeviceResolutionState *R; |
|
601 + unsigned int i; |
|
602 |
|
603 r = (xDeviceResolutionState *) d; |
|
604 R = (XDeviceResolutionState *) Device; |
|
605 -- |
|
606 1.7.9.2 |
|
607 |
|
608 From 9e39ad6e66a517c2324426c3aa32f4cfcc1cd4f5 Mon Sep 17 00:00:00 2001 |
|
609 From: Alan Coopersmith <[email protected]> |
|
610 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
611 Subject: [PATCH:libXi 06/13] integer overflow in XGetFeedbackControl() |
|
612 [CVE-2013-1984 2/8] |
|
613 |
|
614 If the number of feedbacks reported by the server is large enough that |
|
615 it overflows when multiplied by the size of the appropriate struct, or |
|
616 if the total size of all the feedback structures overflows when added |
|
617 together, then memory corruption can occur when more bytes are copied from |
|
618 the X server reply than the size of the buffer we allocated to hold them. |
|
619 |
|
620 v2: check that reply size fits inside the data read from the server, so |
|
621 we don't read out of bounds either |
|
622 |
|
623 Reported-by: Ilja Van Sprundel <[email protected]> |
|
624 Signed-off-by: Alan Coopersmith <[email protected]> |
|
625 Reviewed-by: Peter Hutterer <[email protected]> |
|
626 --- |
|
627 src/XGetFCtl.c | 24 +++++++++++++++++++----- |
|
628 1 file changed, 19 insertions(+), 5 deletions(-) |
|
629 |
|
630 diff --git a/src/XGetFCtl.c b/src/XGetFCtl.c |
|
631 index 28fab4d..bb50bf3 100644 |
|
632 --- a/src/XGetFCtl.c |
|
633 +++ b/src/XGetFCtl.c |
|
634 @@ -61,6 +61,7 @@ SOFTWARE. |
|
635 #include <X11/extensions/XInput.h> |
|
636 #include <X11/extensions/extutil.h> |
|
637 #include "XIint.h" |
|
638 +#include <limits.h> |
|
639 |
|
640 XFeedbackState * |
|
641 XGetFeedbackControl( |
|
642 @@ -68,8 +69,6 @@ XGetFeedbackControl( |
|
643 XDevice *dev, |
|
644 int *num_feedbacks) |
|
645 { |
|
646 - int size = 0; |
|
647 - int nbytes, i; |
|
648 XFeedbackState *Feedback = NULL; |
|
649 XFeedbackState *Sav = NULL; |
|
650 xFeedbackState *f = NULL; |
|
651 @@ -91,9 +90,16 @@ XGetFeedbackControl( |
|
652 goto out; |
|
653 |
|
654 if (rep.length > 0) { |
|
655 + unsigned long nbytes; |
|
656 + size_t size = 0; |
|
657 + int i; |
|
658 + |
|
659 *num_feedbacks = rep.num_feedbacks; |
|
660 - nbytes = (long)rep.length << 2; |
|
661 - f = (xFeedbackState *) Xmalloc((unsigned)nbytes); |
|
662 + |
|
663 + if (rep.length < (INT_MAX >> 2)) { |
|
664 + nbytes = rep.length << 2; |
|
665 + f = Xmalloc(nbytes); |
|
666 + } |
|
667 if (!f) { |
|
668 _XEatDataWords(dpy, rep.length); |
|
669 goto out; |
|
670 @@ -102,6 +108,10 @@ XGetFeedbackControl( |
|
671 _XRead(dpy, (char *)f, nbytes); |
|
672 |
|
673 for (i = 0; i < *num_feedbacks; i++) { |
|
674 + if (f->length > nbytes) |
|
675 + goto out; |
|
676 + nbytes -= f->length; |
|
677 + |
|
678 switch (f->class) { |
|
679 case KbdFeedbackClass: |
|
680 size += sizeof(XKbdFeedbackState); |
|
681 @@ -116,6 +126,8 @@ XGetFeedbackControl( |
|
682 { |
|
683 xStringFeedbackState *strf = (xStringFeedbackState *) f; |
|
684 |
|
685 + if (strf->num_syms_supported >= (INT_MAX / sizeof(KeySym))) |
|
686 + goto out; |
|
687 size += sizeof(XStringFeedbackState) + |
|
688 (strf->num_syms_supported * sizeof(KeySym)); |
|
689 } |
|
690 @@ -130,10 +142,12 @@ XGetFeedbackControl( |
|
691 size += f->length; |
|
692 break; |
|
693 } |
|
694 + if (size > INT_MAX) |
|
695 + goto out; |
|
696 f = (xFeedbackState *) ((char *)f + f->length); |
|
697 } |
|
698 |
|
699 - Feedback = (XFeedbackState *) Xmalloc((unsigned)size); |
|
700 + Feedback = Xmalloc(size); |
|
701 if (!Feedback) |
|
702 goto out; |
|
703 |
|
704 -- |
|
705 1.7.9.2 |
|
706 |
|
707 From 0bb14773ba37dfa8098b3e1784c80658019f9f21 Mon Sep 17 00:00:00 2001 |
|
708 From: Alan Coopersmith <[email protected]> |
|
709 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
710 Subject: [PATCH:libXi 07/13] integer overflow in |
|
711 XGetDeviceDontPropagateList() [CVE-2013-1984 |
|
712 3/8] |
|
713 |
|
714 If the number of event classes reported by the server is large enough |
|
715 that it overflows when multiplied by the size of the appropriate struct, |
|
716 then memory corruption can occur when more bytes are copied from the |
|
717 X server reply than the size of the buffer we allocated to hold them. |
|
718 |
|
719 V2: EatData if count is 0 but length is > 0 to avoid XIOErrors |
|
720 |
|
721 Reported-by: Ilja Van Sprundel <[email protected]> |
|
722 Signed-off-by: Alan Coopersmith <[email protected]> |
|
723 Reviewed-by: Peter Hutterer <[email protected]> |
|
724 --- |
|
725 src/XGetProp.c | 8 +++++--- |
|
726 1 file changed, 5 insertions(+), 3 deletions(-) |
|
727 |
|
728 diff --git a/src/XGetProp.c b/src/XGetProp.c |
|
729 index 34bc581..b49328c 100644 |
|
730 --- a/src/XGetProp.c |
|
731 +++ b/src/XGetProp.c |
|
732 @@ -60,6 +60,7 @@ SOFTWARE. |
|
733 #include <X11/extensions/XInput.h> |
|
734 #include <X11/extensions/extutil.h> |
|
735 #include "XIint.h" |
|
736 +#include <limits.h> |
|
737 |
|
738 XEventClass * |
|
739 XGetDeviceDontPropagateList( |
|
740 @@ -88,10 +89,11 @@ XGetDeviceDontPropagateList( |
|
741 } |
|
742 *count = rep.count; |
|
743 |
|
744 - if (*count) { |
|
745 - list = (XEventClass *) Xmalloc(rep.length * sizeof(XEventClass)); |
|
746 + if (rep.length != 0) { |
|
747 + if ((rep.count != 0) && (rep.length < (INT_MAX / sizeof(XEventClass)))) |
|
748 + list = Xmalloc(rep.length * sizeof(XEventClass)); |
|
749 if (list) { |
|
750 - int i; |
|
751 + unsigned int i; |
|
752 CARD32 ec; |
|
753 |
|
754 /* read and assign each XEventClass separately because |
|
755 -- |
|
756 1.7.9.2 |
|
757 |
|
758 From 3d1fc7cd03e9a41b86cd83a8922df551a1b87179 Mon Sep 17 00:00:00 2001 |
|
759 From: Alan Coopersmith <[email protected]> |
|
760 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
761 Subject: [PATCH:libXi 08/13] integer overflow in XGetDeviceMotionEvents() |
|
762 [CVE-2013-1984 4/8] |
|
763 |
|
764 If the number of events or axes reported by the server is large enough |
|
765 that it overflows when multiplied by the size of the appropriate struct, |
|
766 then memory corruption can occur when more bytes are copied from the |
|
767 X server reply than the size of the buffer we allocated to hold them. |
|
768 |
|
769 Reported-by: Ilja Van Sprundel <[email protected]> |
|
770 Signed-off-by: Alan Coopersmith <[email protected]> |
|
771 Reviewed-by: Peter Hutterer <[email protected]> |
|
772 --- |
|
773 src/XGMotion.c | 22 +++++++++++++++++----- |
|
774 1 file changed, 17 insertions(+), 5 deletions(-) |
|
775 |
|
776 diff --git a/src/XGMotion.c b/src/XGMotion.c |
|
777 index 5feac85..a4c75b6 100644 |
|
778 --- a/src/XGMotion.c |
|
779 +++ b/src/XGMotion.c |
|
780 @@ -59,6 +59,7 @@ SOFTWARE. |
|
781 #include <X11/extensions/XInput.h> |
|
782 #include <X11/extensions/extutil.h> |
|
783 #include "XIint.h" |
|
784 +#include <limits.h> |
|
785 |
|
786 XDeviceTimeCoord * |
|
787 XGetDeviceMotionEvents( |
|
788 @@ -74,7 +75,7 @@ XGetDeviceMotionEvents( |
|
789 xGetDeviceMotionEventsReply rep; |
|
790 XDeviceTimeCoord *tc; |
|
791 int *data, *bufp, *readp, *savp; |
|
792 - long size, size2; |
|
793 + unsigned long size; |
|
794 int i, j; |
|
795 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
796 |
|
797 @@ -104,10 +105,21 @@ XGetDeviceMotionEvents( |
|
798 SyncHandle(); |
|
799 return (NULL); |
|
800 } |
|
801 - size = rep.length << 2; |
|
802 - size2 = rep.nEvents * (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int))); |
|
803 - savp = readp = (int *)Xmalloc(size); |
|
804 - bufp = (int *)Xmalloc(size2); |
|
805 + if (rep.length < (INT_MAX >> 2)) { |
|
806 + size = rep.length << 2; |
|
807 + savp = readp = Xmalloc(size); |
|
808 + } else { |
|
809 + size = 0; |
|
810 + savp = readp = NULL; |
|
811 + } |
|
812 + /* rep.axes is a CARD8, so assume max number of axes for bounds check */ |
|
813 + if (rep.nEvents < |
|
814 + (INT_MAX / (sizeof(XDeviceTimeCoord) + (UCHAR_MAX * sizeof(int))))) { |
|
815 + size_t bsize = rep.nEvents * |
|
816 + (sizeof(XDeviceTimeCoord) + (rep.axes * sizeof(int))); |
|
817 + bufp = Xmalloc(bsize); |
|
818 + } else |
|
819 + bufp = NULL; |
|
820 if (!bufp || !savp) { |
|
821 Xfree(bufp); |
|
822 Xfree(savp); |
|
823 -- |
|
824 1.7.9.2 |
|
825 |
|
826 From 1202a8fc208581e184d327118a8a8ac3a27bbe64 Mon Sep 17 00:00:00 2001 |
|
827 From: Alan Coopersmith <[email protected]> |
|
828 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
829 Subject: [PATCH:libXi 09/13] integer overflow in XIGetProperty() |
|
830 [CVE-2013-1984 5/8] |
|
831 |
|
832 If the number of items reported by the server is large enough that |
|
833 it overflows when multiplied by the size of the appropriate item type, |
|
834 then memory corruption can occur when more bytes are copied from the |
|
835 X server reply than the size of the buffer we allocated to hold them. |
|
836 |
|
837 Reported-by: Ilja Van Sprundel <[email protected]> |
|
838 Signed-off-by: Alan Coopersmith <[email protected]> |
|
839 Reviewed-by: Peter Hutterer <[email protected]> |
|
840 --- |
|
841 src/XIProperties.c | 11 +++++++---- |
|
842 1 file changed, 7 insertions(+), 4 deletions(-) |
|
843 |
|
844 diff --git a/src/XIProperties.c b/src/XIProperties.c |
|
845 index 5e58fb6..32436d1 100644 |
|
846 --- a/src/XIProperties.c |
|
847 +++ b/src/XIProperties.c |
|
848 @@ -38,6 +38,7 @@ |
|
849 #include <X11/extensions/XInput2.h> |
|
850 #include <X11/extensions/extutil.h> |
|
851 #include "XIint.h" |
|
852 +#include <limits.h> |
|
853 |
|
854 Atom* |
|
855 XIListProperties(Display* dpy, int deviceid, int *num_props_return) |
|
856 @@ -170,7 +171,7 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, |
|
857 { |
|
858 xXIGetPropertyReq *req; |
|
859 xXIGetPropertyReply rep; |
|
860 - long nbytes, rbytes; |
|
861 + unsigned long nbytes, rbytes; |
|
862 |
|
863 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
864 |
|
865 @@ -216,9 +217,11 @@ XIGetProperty(Display* dpy, int deviceid, Atom property, long offset, |
|
866 * recopy the string to make it null terminated. |
|
867 */ |
|
868 |
|
869 - nbytes = rep.num_items * rep.format/8; |
|
870 - rbytes = nbytes + 1; |
|
871 - *data = Xmalloc(rbytes); |
|
872 + if (rep.num_items < (INT_MAX / (rep.format/8))) { |
|
873 + nbytes = rep.num_items * rep.format/8; |
|
874 + rbytes = nbytes + 1; |
|
875 + *data = Xmalloc(rbytes); |
|
876 + } |
|
877 |
|
878 if (!(*data)) { |
|
879 _XEatDataWords(dpy, rep.length); |
|
880 -- |
|
881 1.7.9.2 |
|
882 |
|
883 From a3e76afd699b7afa590c8d3567663460c9870924 Mon Sep 17 00:00:00 2001 |
|
884 From: Alan Coopersmith <[email protected]> |
|
885 Date: Sat, 9 Mar 2013 22:55:23 -0800 |
|
886 Subject: [PATCH:libXi 10/13] integer overflow in XIGetSelectedEvents() |
|
887 [CVE-2013-1984 6/8] |
|
888 |
|
889 If the number of events or masks reported by the server is large enough |
|
890 that it overflows when multiplied by the size of the appropriate struct, |
|
891 or the sizes overflow as they are totaled up, then memory corruption can |
|
892 occur when more bytes are copied from the X server reply than the size |
|
893 of the buffer we allocated to hold them. |
|
894 |
|
895 v2: check that reply size fits inside the data read from the server, |
|
896 so that we don't read out of bounds either |
|
897 |
|
898 Reported-by: Ilja Van Sprundel <[email protected]> |
|
899 Signed-off-by: Alan Coopersmith <[email protected]> |
|
900 Reviewed-by: Peter Hutterer <[email protected]> |
|
901 --- |
|
902 src/XISelEv.c | 25 +++++++++++++++++++------ |
|
903 1 file changed, 19 insertions(+), 6 deletions(-) |
|
904 |
|
905 diff --git a/src/XISelEv.c b/src/XISelEv.c |
|
906 index f871222..0471bef 100644 |
|
907 --- a/src/XISelEv.c |
|
908 +++ b/src/XISelEv.c |
|
909 @@ -42,6 +42,7 @@ in this Software without prior written authorization from the author. |
|
910 #include <X11/extensions/ge.h> |
|
911 #include <X11/extensions/geproto.h> |
|
912 #include "XIint.h" |
|
913 +#include <limits.h> |
|
914 |
|
915 int |
|
916 XISelectEvents(Display* dpy, Window win, XIEventMask* masks, int num_masks) |
|
917 @@ -101,13 +102,14 @@ out: |
|
918 XIEventMask* |
|
919 XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) |
|
920 { |
|
921 - int i, len = 0; |
|
922 + unsigned int i, len = 0; |
|
923 unsigned char *mask; |
|
924 XIEventMask *mask_out = NULL; |
|
925 xXIEventMask *mask_in = NULL, *mi; |
|
926 xXIGetSelectedEventsReq *req; |
|
927 xXIGetSelectedEventsReply reply; |
|
928 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
929 + size_t rbytes; |
|
930 |
|
931 *num_masks_return = -1; |
|
932 LockDisplay(dpy); |
|
933 @@ -129,11 +131,16 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) |
|
934 goto out; |
|
935 } |
|
936 |
|
937 - mask_in = Xmalloc(reply.length * 4); |
|
938 - if (!mask_in) |
|
939 + if (reply.length < (INT_MAX >> 2)) { |
|
940 + rbytes = (unsigned long) reply.length << 2; |
|
941 + mask_in = Xmalloc(rbytes); |
|
942 + } |
|
943 + if (!mask_in) { |
|
944 + _XEatDataWords(dpy, reply.length); |
|
945 goto out; |
|
946 + } |
|
947 |
|
948 - _XRead(dpy, (char*)mask_in, reply.length * 4); |
|
949 + _XRead(dpy, (char*)mask_in, rbytes); |
|
950 |
|
951 /* |
|
952 * This function takes interleaved xXIEventMask structs & masks off |
|
953 @@ -148,8 +155,14 @@ XIGetSelectedEvents(Display* dpy, Window win, int *num_masks_return) |
|
954 |
|
955 for (i = 0, mi = mask_in; i < reply.num_masks; i++) |
|
956 { |
|
957 - len += mi->mask_len * 4; |
|
958 - mi = (xXIEventMask*)((char*)mi + mi->mask_len * 4); |
|
959 + unsigned int mask_bytes = mi->mask_len * 4; |
|
960 + len += mask_bytes; |
|
961 + if (len > INT_MAX) |
|
962 + goto out; |
|
963 + if ((sizeof(xXIEventMask) + mask_bytes) > rbytes) |
|
964 + goto out; |
|
965 + rbytes -= (sizeof(xXIEventMask) + mask_bytes); |
|
966 + mi = (xXIEventMask*)((char*)mi + mask_bytes); |
|
967 mi++; |
|
968 } |
|
969 |
|
970 -- |
|
971 1.7.9.2 |
|
972 |
|
973 From b6246afd838842d28ac94d901507390624f31c7d Mon Sep 17 00:00:00 2001 |
|
974 From: Alan Coopersmith <[email protected]> |
|
975 Date: Sun, 10 Mar 2013 13:30:55 -0700 |
|
976 Subject: [PATCH:libXi 11/13] Avoid integer overflow in XGetDeviceProperties() |
|
977 [CVE-2013-1984 7/8] |
|
978 |
|
979 If the number of items as reported by the Xserver is too large, it |
|
980 could overflow the calculation for the size of the buffer to copy the |
|
981 reply into, causing memory corruption. |
|
982 |
|
983 Signed-off-by: Alan Coopersmith <[email protected]> |
|
984 Reviewed-by: Peter Hutterer <[email protected]> |
|
985 --- |
|
986 src/XGetDProp.c | 61 +++++++++++++++++++++++++++++++++---------------------- |
|
987 1 file changed, 37 insertions(+), 24 deletions(-) |
|
988 |
|
989 diff --git a/src/XGetDProp.c b/src/XGetDProp.c |
|
990 index f9e8f0c..3691122 100644 |
|
991 --- a/src/XGetDProp.c |
|
992 +++ b/src/XGetDProp.c |
|
993 @@ -38,6 +38,7 @@ in this Software without prior written authorization from the author. |
|
994 #include <X11/extensions/XInput.h> |
|
995 #include <X11/extensions/extutil.h> |
|
996 #include "XIint.h" |
|
997 +#include <limits.h> |
|
998 |
|
999 int |
|
1000 XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
1001 @@ -48,7 +49,8 @@ XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
1002 { |
|
1003 xGetDevicePropertyReq *req; |
|
1004 xGetDevicePropertyReply rep; |
|
1005 - long nbytes, rbytes; |
|
1006 + unsigned long nbytes, rbytes; |
|
1007 + int ret = Success; |
|
1008 |
|
1009 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
1010 |
|
1011 @@ -81,30 +83,43 @@ XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
1012 * data, but this last byte is null terminated and convenient for |
|
1013 * returning string properties, so the client doesn't then have to |
|
1014 * recopy the string to make it null terminated. |
|
1015 + * |
|
1016 + * Maximum item limits are set to both prevent integer overflow when |
|
1017 + * calculating the amount of memory to malloc, and to limit how much |
|
1018 + * memory will be used if a server provides an insanely high count. |
|
1019 */ |
|
1020 switch (rep.format) { |
|
1021 case 8: |
|
1022 - nbytes = rep.nItems; |
|
1023 - rbytes = rep.nItems + 1; |
|
1024 - if (rbytes > 0 && |
|
1025 - (*prop = (unsigned char *) Xmalloc ((unsigned)rbytes))) |
|
1026 - _XReadPad (dpy, (char *) *prop, nbytes); |
|
1027 + if (rep.nItems < INT_MAX) { |
|
1028 + nbytes = rep.nItems; |
|
1029 + rbytes = rep.nItems + 1; |
|
1030 + if ((*prop = Xmalloc (rbytes))) |
|
1031 + _XReadPad (dpy, (char *) *prop, nbytes); |
|
1032 + else |
|
1033 + ret = BadAlloc; |
|
1034 + } |
|
1035 break; |
|
1036 |
|
1037 case 16: |
|
1038 - nbytes = rep.nItems << 1; |
|
1039 - rbytes = rep.nItems * sizeof (short) + 1; |
|
1040 - if (rbytes > 0 && |
|
1041 - (*prop = (unsigned char *) Xmalloc ((unsigned)rbytes))) |
|
1042 - _XRead16Pad (dpy, (short *) *prop, nbytes); |
|
1043 + if (rep.nItems < (INT_MAX / sizeof (short))) { |
|
1044 + nbytes = rep.nItems << 1; |
|
1045 + rbytes = rep.nItems * sizeof (short) + 1; |
|
1046 + if ((*prop = Xmalloc (rbytes))) |
|
1047 + _XRead16Pad (dpy, (short *) *prop, nbytes); |
|
1048 + else |
|
1049 + ret = BadAlloc; |
|
1050 + } |
|
1051 break; |
|
1052 |
|
1053 case 32: |
|
1054 - nbytes = rep.nItems << 2; |
|
1055 - rbytes = rep.nItems * sizeof (long) + 1; |
|
1056 - if (rbytes > 0 && |
|
1057 - (*prop = (unsigned char *) Xmalloc ((unsigned)rbytes))) |
|
1058 - _XRead32 (dpy, (long *) *prop, nbytes); |
|
1059 + if (rep.nItems < (INT_MAX / sizeof (long))) { |
|
1060 + nbytes = rep.nItems << 2; |
|
1061 + rbytes = rep.nItems * sizeof (long) + 1; |
|
1062 + if ((*prop = Xmalloc (rbytes))) |
|
1063 + _XRead32 (dpy, (long *) *prop, nbytes); |
|
1064 + else |
|
1065 + ret = BadAlloc; |
|
1066 + } |
|
1067 break; |
|
1068 |
|
1069 default: |
|
1070 @@ -112,16 +127,13 @@ XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
1071 * This part of the code should never be reached. If it is, |
|
1072 * the server sent back a property with an invalid format. |
|
1073 */ |
|
1074 - _XEatDataWords(dpy, rep.length); |
|
1075 - UnlockDisplay(dpy); |
|
1076 - SyncHandle(); |
|
1077 - return(BadImplementation); |
|
1078 + ret = BadImplementation; |
|
1079 } |
|
1080 if (! *prop) { |
|
1081 _XEatDataWords(dpy, rep.length); |
|
1082 - UnlockDisplay(dpy); |
|
1083 - SyncHandle(); |
|
1084 - return(BadAlloc); |
|
1085 + if (ret == Success) |
|
1086 + ret = BadAlloc; |
|
1087 + goto out; |
|
1088 } |
|
1089 (*prop)[rbytes - 1] = '\0'; |
|
1090 } |
|
1091 @@ -130,9 +142,10 @@ XGetDeviceProperty(Display* dpy, XDevice* dev, |
|
1092 *actual_format = rep.format; |
|
1093 *nitems = rep.nItems; |
|
1094 *bytes_after = rep.bytesAfter; |
|
1095 + out: |
|
1096 UnlockDisplay (dpy); |
|
1097 SyncHandle (); |
|
1098 |
|
1099 - return Success; |
|
1100 + return ret; |
|
1101 } |
|
1102 |
|
1103 -- |
|
1104 1.7.9.2 |
|
1105 |
|
1106 From 03f9746651d8d67c6d449737bd1681eb394b094c Mon Sep 17 00:00:00 2001 |
|
1107 From: Alan Coopersmith <[email protected]> |
|
1108 Date: Sun, 10 Mar 2013 00:22:14 -0800 |
|
1109 Subject: [PATCH:libXi 12/13] Avoid integer overflow in XListInputDevices() |
|
1110 [CVE-2013-1984 8/8] |
|
1111 |
|
1112 If the length of the reply as reported by the Xserver is too long, it |
|
1113 could overflow the calculation for the size of the buffer to copy the |
|
1114 reply into, causing memory corruption. |
|
1115 |
|
1116 Signed-off-by: Alan Coopersmith <[email protected]> |
|
1117 Reviewed-by: Peter Hutterer <[email protected]> |
|
1118 --- |
|
1119 src/XListDev.c | 10 ++++++---- |
|
1120 1 file changed, 6 insertions(+), 4 deletions(-) |
|
1121 |
|
1122 diff --git a/src/XListDev.c b/src/XListDev.c |
|
1123 index 1fa4747..1c14b96 100644 |
|
1124 --- a/src/XListDev.c |
|
1125 +++ b/src/XListDev.c |
|
1126 @@ -60,6 +60,7 @@ SOFTWARE. |
|
1127 #include <X11/extensions/XInput.h> |
|
1128 #include <X11/extensions/extutil.h> |
|
1129 #include "XIint.h" |
|
1130 +#include <limits.h> |
|
1131 |
|
1132 /* Calculate length field to a multiples of sizeof(XID). XIDs are typedefs |
|
1133 * to ulong and thus may be 8 bytes on some platforms. This can trigger a |
|
1134 @@ -179,7 +180,7 @@ XListInputDevices( |
|
1135 XAnyClassPtr Any; |
|
1136 char *nptr, *Nptr; |
|
1137 int i; |
|
1138 - long rlen; |
|
1139 + unsigned long rlen; |
|
1140 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
1141 |
|
1142 LockDisplay(dpy); |
|
1143 @@ -198,9 +199,10 @@ XListInputDevices( |
|
1144 |
|
1145 if ((*ndevices = rep.ndevices)) { /* at least 1 input device */ |
|
1146 size = *ndevices * sizeof(XDeviceInfo); |
|
1147 - rlen = rep.length << 2; /* multiply length by 4 */ |
|
1148 - list = (xDeviceInfo *) Xmalloc(rlen); |
|
1149 - slist = list; |
|
1150 + if (rep.length < (INT_MAX >> 2)) { |
|
1151 + rlen = rep.length << 2; /* multiply length by 4 */ |
|
1152 + slist = list = Xmalloc(rlen); |
|
1153 + } |
|
1154 if (!slist) { |
|
1155 _XEatDataWords(dpy, rep.length); |
|
1156 UnlockDisplay(dpy); |
|
1157 -- |
|
1158 1.7.9.2 |
|
1159 |
|
1160 From 5019f7a8f06b6826cd197d8def6feb841f1490ec Mon Sep 17 00:00:00 2001 |
|
1161 From: Alan Coopersmith <[email protected]> |
|
1162 Date: Sun, 10 Mar 2013 00:16:22 -0800 |
|
1163 Subject: [PATCH:libXi 13/13] sign extension issue in XListInputDevices() |
|
1164 [CVE-2013-1995] |
|
1165 |
|
1166 nptr is (signed) char, which can be negative, and will sign extend |
|
1167 when added to the int size, which means size can be subtracted from, |
|
1168 leading to allocating too small a buffer to hold the data being copied |
|
1169 from the X server's reply. |
|
1170 |
|
1171 v2: check that string size fits inside the data read from the server, |
|
1172 so that we don't read out of bounds either |
|
1173 |
|
1174 Reported-by: Ilja Van Sprundel <[email protected]> |
|
1175 Signed-off-by: Alan Coopersmith <[email protected]> |
|
1176 Reviewed-by: Peter Hutterer <[email protected]> |
|
1177 --- |
|
1178 src/XListDev.c | 16 ++++++++++------ |
|
1179 1 file changed, 10 insertions(+), 6 deletions(-) |
|
1180 |
|
1181 diff --git a/src/XListDev.c b/src/XListDev.c |
|
1182 index 1c14b96..b85ff3c 100644 |
|
1183 --- a/src/XListDev.c |
|
1184 +++ b/src/XListDev.c |
|
1185 @@ -73,7 +73,7 @@ static int pad_to_xid(int base_size) |
|
1186 return ((base_size + padsize - 1)/padsize) * padsize; |
|
1187 } |
|
1188 |
|
1189 -static int |
|
1190 +static size_t |
|
1191 SizeClassInfo(xAnyClassPtr *any, int num_classes) |
|
1192 { |
|
1193 int size = 0; |
|
1194 @@ -170,7 +170,7 @@ XListInputDevices( |
|
1195 register Display *dpy, |
|
1196 int *ndevices) |
|
1197 { |
|
1198 - int size; |
|
1199 + size_t size; |
|
1200 xListInputDevicesReq *req; |
|
1201 xListInputDevicesReply rep; |
|
1202 xDeviceInfo *list, *slist = NULL; |
|
1203 @@ -178,7 +178,7 @@ XListInputDevices( |
|
1204 XDeviceInfo *clist = NULL; |
|
1205 xAnyClassPtr any, sav_any; |
|
1206 XAnyClassPtr Any; |
|
1207 - char *nptr, *Nptr; |
|
1208 + unsigned char *nptr, *Nptr; |
|
1209 int i; |
|
1210 unsigned long rlen; |
|
1211 XExtDisplayInfo *info = XInput_find_display(dpy); |
|
1212 @@ -217,9 +217,12 @@ XListInputDevices( |
|
1213 size += SizeClassInfo(&any, (int)list->num_classes); |
|
1214 } |
|
1215 |
|
1216 - for (i = 0, nptr = (char *)any; i < *ndevices; i++) { |
|
1217 + Nptr = ((unsigned char *)list) + rlen + 1; |
|
1218 + for (i = 0, nptr = (unsigned char *)any; i < *ndevices; i++) { |
|
1219 size += *nptr + 1; |
|
1220 nptr += (*nptr + 1); |
|
1221 + if (nptr > Nptr) |
|
1222 + goto out; |
|
1223 } |
|
1224 |
|
1225 clist = (XDeviceInfoPtr) Xmalloc(size); |
|
1226 @@ -245,8 +248,8 @@ XListInputDevices( |
|
1227 } |
|
1228 |
|
1229 clist = sclist; |
|
1230 - nptr = (char *)any; |
|
1231 - Nptr = (char *)Any; |
|
1232 + nptr = (unsigned char *)any; |
|
1233 + Nptr = (unsigned char *)Any; |
|
1234 for (i = 0; i < *ndevices; i++, clist++) { |
|
1235 clist->name = (char *)Nptr; |
|
1236 memcpy(Nptr, nptr + 1, *nptr); |
|
1237 @@ -256,6 +259,7 @@ XListInputDevices( |
|
1238 } |
|
1239 } |
|
1240 |
|
1241 + out: |
|
1242 XFree((char *)slist); |
|
1243 UnlockDisplay(dpy); |
|
1244 SyncHandle(); |
|
1245 -- |
|
1246 1.7.9.2 |
|
1247 |