Commit | Line | Data |
---|---|---|
7217e0ca ML |
1 | From 54fa1f815507cd27280f661be7a64f2f2e6c579e Mon Sep 17 00:00:00 2001 |
2 | From: Alan Coopersmith <alan.coopersmith@oracle.com> | |
3 | Date: Sun, 26 Jan 2014 10:54:41 -0800 | |
4 | Subject: [PATCH 08/33] Xi: unvalidated lengths in Xinput extension | |
5 | [CVE-2014-8095] | |
6 | ||
7 | Multiple functions in the Xinput extension handling of requests from | |
8 | clients failed to check that the length of the request sent by the | |
9 | client was large enough to perform all the required operations and | |
10 | thus could read or write to memory outside the bounds of the request | |
11 | buffer. | |
12 | ||
13 | This commit includes the creation of a new REQUEST_AT_LEAST_EXTRA_SIZE | |
14 | macro in include/dix.h for the common case of needing to ensure a | |
15 | request is large enough to include both the request itself and a | |
16 | minimum amount of extra data following the request header. | |
17 | ||
18 | Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com> | |
19 | Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> | |
20 | --- | |
21 | Xi/chgdctl.c | 8 ++++++-- | |
22 | Xi/chgfctl.c | 2 ++ | |
23 | Xi/sendexev.c | 3 +++ | |
24 | Xi/xiallowev.c | 2 ++ | |
25 | Xi/xichangecursor.c | 2 +- | |
26 | Xi/xichangehierarchy.c | 35 ++++++++++++++++++++++++++++++++--- | |
27 | Xi/xigetclientpointer.c | 1 + | |
28 | Xi/xigrabdev.c | 9 ++++++++- | |
29 | Xi/xipassivegrab.c | 12 ++++++++++-- | |
30 | Xi/xiproperty.c | 14 ++++++-------- | |
31 | Xi/xiquerydevice.c | 1 + | |
32 | Xi/xiquerypointer.c | 2 ++ | |
33 | Xi/xiselectev.c | 8 ++++++++ | |
34 | Xi/xisetclientpointer.c | 3 ++- | |
35 | Xi/xisetdevfocus.c | 4 ++++ | |
36 | Xi/xiwarppointer.c | 2 ++ | |
37 | include/dix.h | 4 ++++ | |
38 | 17 files changed, 94 insertions(+), 18 deletions(-) | |
39 | ||
40 | diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c | |
41 | index d078aa2..b3ee867 100644 | |
42 | --- a/Xi/chgdctl.c | |
43 | +++ b/Xi/chgdctl.c | |
44 | @@ -78,7 +78,7 @@ SProcXChangeDeviceControl(ClientPtr client) | |
45 | ||
46 | REQUEST(xChangeDeviceControlReq); | |
47 | swaps(&stuff->length); | |
48 | - REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); | |
49 | + REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); | |
50 | swaps(&stuff->control); | |
51 | ctl = (xDeviceCtl *) &stuff[1]; | |
52 | swaps(&ctl->control); | |
53 | @@ -115,7 +115,7 @@ ProcXChangeDeviceControl(ClientPtr client) | |
54 | xDeviceEnableCtl *e; | |
55 | ||
56 | REQUEST(xChangeDeviceControlReq); | |
57 | - REQUEST_AT_LEAST_SIZE(xChangeDeviceControlReq); | |
58 | + REQUEST_AT_LEAST_EXTRA_SIZE(xChangeDeviceControlReq, sizeof(xDeviceCtl)); | |
59 | ||
60 | len = stuff->length - bytes_to_int32(sizeof(xChangeDeviceControlReq)); | |
61 | ret = dixLookupDevice(&dev, stuff->deviceid, client, DixManageAccess); | |
62 | @@ -192,6 +192,10 @@ ProcXChangeDeviceControl(ClientPtr client) | |
63 | break; | |
64 | case DEVICE_ENABLE: | |
65 | e = (xDeviceEnableCtl *) &stuff[1]; | |
66 | + if ((len != bytes_to_int32(sizeof(xDeviceEnableCtl)))) { | |
67 | + ret = BadLength; | |
68 | + goto out; | |
69 | + } | |
70 | ||
71 | if (IsXTestDevice(dev, NULL)) | |
72 | status = !Success; | |
73 | diff --git a/Xi/chgfctl.c b/Xi/chgfctl.c | |
74 | index 6dcf60c..224c2ba 100644 | |
75 | --- a/Xi/chgfctl.c | |
76 | +++ b/Xi/chgfctl.c | |
77 | @@ -467,6 +467,8 @@ ProcXChangeFeedbackControl(ClientPtr client) | |
78 | xStringFeedbackCtl *f = ((xStringFeedbackCtl *) &stuff[1]); | |
79 | ||
80 | if (client->swapped) { | |
81 | + if (len < bytes_to_int32(sizeof(xStringFeedbackCtl))) | |
82 | + return BadLength; | |
83 | swaps(&f->num_keysyms); | |
84 | } | |
85 | if (len != | |
86 | diff --git a/Xi/sendexev.c b/Xi/sendexev.c | |
87 | index 3c21386..183f88d 100644 | |
88 | --- a/Xi/sendexev.c | |
89 | +++ b/Xi/sendexev.c | |
90 | @@ -135,6 +135,9 @@ ProcXSendExtensionEvent(ClientPtr client) | |
91 | if (ret != Success) | |
92 | return ret; | |
93 | ||
94 | + if (stuff->num_events == 0) | |
95 | + return ret; | |
96 | + | |
97 | /* The client's event type must be one defined by an extension. */ | |
98 | ||
99 | first = ((xEvent *) &stuff[1]); | |
100 | diff --git a/Xi/xiallowev.c b/Xi/xiallowev.c | |
101 | index ebef233..ca263ef 100644 | |
102 | --- a/Xi/xiallowev.c | |
103 | +++ b/Xi/xiallowev.c | |
104 | @@ -48,6 +48,7 @@ int | |
105 | SProcXIAllowEvents(ClientPtr client) | |
106 | { | |
107 | REQUEST(xXIAllowEventsReq); | |
108 | + REQUEST_AT_LEAST_SIZE(xXIAllowEventsReq); | |
109 | ||
110 | swaps(&stuff->length); | |
111 | swaps(&stuff->deviceid); | |
112 | @@ -55,6 +56,7 @@ SProcXIAllowEvents(ClientPtr client) | |
113 | if (stuff->length > 3) { | |
114 | xXI2_2AllowEventsReq *req_xi22 = (xXI2_2AllowEventsReq *) stuff; | |
115 | ||
116 | + REQUEST_AT_LEAST_SIZE(xXI2_2AllowEventsReq); | |
117 | swapl(&req_xi22->touchid); | |
118 | swapl(&req_xi22->grab_window); | |
119 | } | |
120 | diff --git a/Xi/xichangecursor.c b/Xi/xichangecursor.c | |
121 | index 7a1bb7a..8e6255b 100644 | |
122 | --- a/Xi/xichangecursor.c | |
123 | +++ b/Xi/xichangecursor.c | |
124 | @@ -57,11 +57,11 @@ int | |
125 | SProcXIChangeCursor(ClientPtr client) | |
126 | { | |
127 | REQUEST(xXIChangeCursorReq); | |
128 | + REQUEST_SIZE_MATCH(xXIChangeCursorReq); | |
129 | swaps(&stuff->length); | |
130 | swapl(&stuff->win); | |
131 | swapl(&stuff->cursor); | |
132 | swaps(&stuff->deviceid); | |
133 | - REQUEST_SIZE_MATCH(xXIChangeCursorReq); | |
134 | return (ProcXIChangeCursor(client)); | |
135 | } | |
136 | ||
137 | diff --git a/Xi/xichangehierarchy.c b/Xi/xichangehierarchy.c | |
138 | index 9e36354..2732445 100644 | |
139 | --- a/Xi/xichangehierarchy.c | |
140 | +++ b/Xi/xichangehierarchy.c | |
141 | @@ -411,7 +411,7 @@ int | |
142 | ProcXIChangeHierarchy(ClientPtr client) | |
143 | { | |
144 | xXIAnyHierarchyChangeInfo *any; | |
145 | - int required_len = sizeof(xXIChangeHierarchyReq); | |
146 | + size_t len; /* length of data remaining in request */ | |
147 | int rc = Success; | |
148 | int flags[MAXDEVICES] = { 0 }; | |
149 | ||
150 | @@ -421,21 +421,46 @@ ProcXIChangeHierarchy(ClientPtr client) | |
151 | if (!stuff->num_changes) | |
152 | return rc; | |
153 | ||
154 | + if (stuff->length > (INT_MAX >> 2)) | |
155 | + return BadAlloc; | |
156 | + len = (stuff->length << 2) - sizeof(xXIAnyHierarchyChangeInfo); | |
157 | + | |
158 | any = (xXIAnyHierarchyChangeInfo *) &stuff[1]; | |
159 | while (stuff->num_changes--) { | |
160 | + if (len < sizeof(xXIAnyHierarchyChangeInfo)) { | |
161 | + rc = BadLength; | |
162 | + goto unwind; | |
163 | + } | |
164 | + | |
165 | SWAPIF(swaps(&any->type)); | |
166 | SWAPIF(swaps(&any->length)); | |
167 | ||
168 | - required_len += any->length; | |
169 | - if ((stuff->length * 4) < required_len) | |
170 | + if ((any->length > (INT_MAX >> 2)) || (len < (any->length << 2))) | |
171 | return BadLength; | |
172 | ||
173 | +#define CHANGE_SIZE_MATCH(type) \ | |
174 | + do { \ | |
175 | + if ((len < sizeof(type)) || (any->length != (sizeof(type) >> 2))) { \ | |
176 | + rc = BadLength; \ | |
177 | + goto unwind; \ | |
178 | + } \ | |
179 | + } while(0) | |
180 | + | |
181 | switch (any->type) { | |
182 | case XIAddMaster: | |
183 | { | |
184 | xXIAddMasterInfo *c = (xXIAddMasterInfo *) any; | |
185 | ||
186 | + /* Variable length, due to appended name string */ | |
187 | + if (len < sizeof(xXIAddMasterInfo)) { | |
188 | + rc = BadLength; | |
189 | + goto unwind; | |
190 | + } | |
191 | SWAPIF(swaps(&c->name_len)); | |
192 | + if (c->name_len > (len - sizeof(xXIAddMasterInfo))) { | |
193 | + rc = BadLength; | |
194 | + goto unwind; | |
195 | + } | |
196 | ||
197 | rc = add_master(client, c, flags); | |
198 | if (rc != Success) | |
199 | @@ -446,6 +471,7 @@ ProcXIChangeHierarchy(ClientPtr client) | |
200 | { | |
201 | xXIRemoveMasterInfo *r = (xXIRemoveMasterInfo *) any; | |
202 | ||
203 | + CHANGE_SIZE_MATCH(xXIRemoveMasterInfo); | |
204 | rc = remove_master(client, r, flags); | |
205 | if (rc != Success) | |
206 | goto unwind; | |
207 | @@ -455,6 +481,7 @@ ProcXIChangeHierarchy(ClientPtr client) | |
208 | { | |
209 | xXIDetachSlaveInfo *c = (xXIDetachSlaveInfo *) any; | |
210 | ||
211 | + CHANGE_SIZE_MATCH(xXIDetachSlaveInfo); | |
212 | rc = detach_slave(client, c, flags); | |
213 | if (rc != Success) | |
214 | goto unwind; | |
215 | @@ -464,6 +491,7 @@ ProcXIChangeHierarchy(ClientPtr client) | |
216 | { | |
217 | xXIAttachSlaveInfo *c = (xXIAttachSlaveInfo *) any; | |
218 | ||
219 | + CHANGE_SIZE_MATCH(xXIAttachSlaveInfo); | |
220 | rc = attach_slave(client, c, flags); | |
221 | if (rc != Success) | |
222 | goto unwind; | |
223 | @@ -471,6 +499,7 @@ ProcXIChangeHierarchy(ClientPtr client) | |
224 | break; | |
225 | } | |
226 | ||
227 | + len -= any->length * 4; | |
228 | any = (xXIAnyHierarchyChangeInfo *) ((char *) any + any->length * 4); | |
229 | } | |
230 | ||
231 | diff --git a/Xi/xigetclientpointer.c b/Xi/xigetclientpointer.c | |
232 | index 3c90d58..306dd39 100644 | |
233 | --- a/Xi/xigetclientpointer.c | |
234 | +++ b/Xi/xigetclientpointer.c | |
235 | @@ -50,6 +50,7 @@ int | |
236 | SProcXIGetClientPointer(ClientPtr client) | |
237 | { | |
238 | REQUEST(xXIGetClientPointerReq); | |
239 | + REQUEST_SIZE_MATCH(xXIGetClientPointerReq); | |
240 | ||
241 | swaps(&stuff->length); | |
242 | swapl(&stuff->win); | |
243 | diff --git a/Xi/xigrabdev.c b/Xi/xigrabdev.c | |
244 | index 63d95bc..e2a2ae3 100644 | |
245 | --- a/Xi/xigrabdev.c | |
246 | +++ b/Xi/xigrabdev.c | |
247 | @@ -47,6 +47,11 @@ int | |
248 | SProcXIGrabDevice(ClientPtr client) | |
249 | { | |
250 | REQUEST(xXIGrabDeviceReq); | |
251 | + /* | |
252 | + * Check here for at least the length of the struct we swap, then | |
253 | + * let ProcXIGrabDevice check the full size after we swap mask_len. | |
254 | + */ | |
255 | + REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq); | |
256 | ||
257 | swaps(&stuff->length); | |
258 | swaps(&stuff->deviceid); | |
259 | @@ -71,7 +76,7 @@ ProcXIGrabDevice(ClientPtr client) | |
260 | unsigned int pointer_mode; | |
261 | ||
262 | REQUEST(xXIGrabDeviceReq); | |
263 | - REQUEST_AT_LEAST_SIZE(xXIGrabDeviceReq); | |
264 | + REQUEST_FIXED_SIZE(xXIGrabDeviceReq, ((size_t) stuff->mask_len) * 4); | |
265 | ||
266 | ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); | |
267 | if (ret != Success) | |
268 | @@ -131,6 +136,7 @@ int | |
269 | SProcXIUngrabDevice(ClientPtr client) | |
270 | { | |
271 | REQUEST(xXIUngrabDeviceReq); | |
272 | + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); | |
273 | ||
274 | swaps(&stuff->length); | |
275 | swaps(&stuff->deviceid); | |
276 | @@ -148,6 +154,7 @@ ProcXIUngrabDevice(ClientPtr client) | |
277 | TimeStamp time; | |
278 | ||
279 | REQUEST(xXIUngrabDeviceReq); | |
280 | + REQUEST_SIZE_MATCH(xXIUngrabDeviceReq); | |
281 | ||
282 | ret = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); | |
283 | if (ret != Success) | |
284 | diff --git a/Xi/xipassivegrab.c b/Xi/xipassivegrab.c | |
285 | index 700622d..9241ffd 100644 | |
286 | --- a/Xi/xipassivegrab.c | |
287 | +++ b/Xi/xipassivegrab.c | |
288 | @@ -53,6 +53,7 @@ SProcXIPassiveGrabDevice(ClientPtr client) | |
289 | uint32_t *mods; | |
290 | ||
291 | REQUEST(xXIPassiveGrabDeviceReq); | |
292 | + REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); | |
293 | ||
294 | swaps(&stuff->length); | |
295 | swaps(&stuff->deviceid); | |
296 | @@ -63,6 +64,8 @@ SProcXIPassiveGrabDevice(ClientPtr client) | |
297 | swaps(&stuff->mask_len); | |
298 | swaps(&stuff->num_modifiers); | |
299 | ||
300 | + REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, | |
301 | + ((uint32_t) stuff->mask_len + stuff->num_modifiers) *4); | |
302 | mods = (uint32_t *) &stuff[1] + stuff->mask_len; | |
303 | ||
304 | for (i = 0; i < stuff->num_modifiers; i++, mods++) { | |
305 | @@ -92,7 +95,8 @@ ProcXIPassiveGrabDevice(ClientPtr client) | |
306 | int mask_len; | |
307 | ||
308 | REQUEST(xXIPassiveGrabDeviceReq); | |
309 | - REQUEST_AT_LEAST_SIZE(xXIPassiveGrabDeviceReq); | |
310 | + REQUEST_FIXED_SIZE(xXIPassiveGrabDeviceReq, | |
311 | + ((uint32_t) stuff->mask_len + stuff->num_modifiers) * 4); | |
312 | ||
313 | if (stuff->deviceid == XIAllDevices) | |
314 | dev = inputInfo.all_devices; | |
315 | @@ -252,6 +256,7 @@ SProcXIPassiveUngrabDevice(ClientPtr client) | |
316 | uint32_t *modifiers; | |
317 | ||
318 | REQUEST(xXIPassiveUngrabDeviceReq); | |
319 | + REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); | |
320 | ||
321 | swaps(&stuff->length); | |
322 | swapl(&stuff->grab_window); | |
323 | @@ -259,6 +264,8 @@ SProcXIPassiveUngrabDevice(ClientPtr client) | |
324 | swapl(&stuff->detail); | |
325 | swaps(&stuff->num_modifiers); | |
326 | ||
327 | + REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, | |
328 | + ((uint32_t) stuff->num_modifiers) << 2); | |
329 | modifiers = (uint32_t *) &stuff[1]; | |
330 | ||
331 | for (i = 0; i < stuff->num_modifiers; i++, modifiers++) | |
332 | @@ -277,7 +284,8 @@ ProcXIPassiveUngrabDevice(ClientPtr client) | |
333 | int i, rc; | |
334 | ||
335 | REQUEST(xXIPassiveUngrabDeviceReq); | |
336 | - REQUEST_AT_LEAST_SIZE(xXIPassiveUngrabDeviceReq); | |
337 | + REQUEST_FIXED_SIZE(xXIPassiveUngrabDeviceReq, | |
338 | + ((uint32_t) stuff->num_modifiers) << 2); | |
339 | ||
340 | if (stuff->deviceid == XIAllDevices) | |
341 | dev = inputInfo.all_devices; | |
342 | diff --git a/Xi/xiproperty.c b/Xi/xiproperty.c | |
343 | index 463607d..8e8e4b0 100644 | |
344 | --- a/Xi/xiproperty.c | |
345 | +++ b/Xi/xiproperty.c | |
346 | @@ -1013,10 +1013,9 @@ int | |
347 | SProcXListDeviceProperties(ClientPtr client) | |
348 | { | |
349 | REQUEST(xListDevicePropertiesReq); | |
350 | + REQUEST_SIZE_MATCH(xListDevicePropertiesReq); | |
351 | ||
352 | swaps(&stuff->length); | |
353 | - | |
354 | - REQUEST_SIZE_MATCH(xListDevicePropertiesReq); | |
355 | return (ProcXListDeviceProperties(client)); | |
356 | } | |
357 | ||
358 | @@ -1037,10 +1036,10 @@ int | |
359 | SProcXDeleteDeviceProperty(ClientPtr client) | |
360 | { | |
361 | REQUEST(xDeleteDevicePropertyReq); | |
362 | + REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); | |
363 | ||
364 | swaps(&stuff->length); | |
365 | swapl(&stuff->property); | |
366 | - REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq); | |
367 | return (ProcXDeleteDeviceProperty(client)); | |
368 | } | |
369 | ||
370 | @@ -1048,13 +1047,13 @@ int | |
371 | SProcXGetDeviceProperty(ClientPtr client) | |
372 | { | |
373 | REQUEST(xGetDevicePropertyReq); | |
374 | + REQUEST_SIZE_MATCH(xGetDevicePropertyReq); | |
375 | ||
376 | swaps(&stuff->length); | |
377 | swapl(&stuff->property); | |
378 | swapl(&stuff->type); | |
379 | swapl(&stuff->longOffset); | |
380 | swapl(&stuff->longLength); | |
381 | - REQUEST_SIZE_MATCH(xGetDevicePropertyReq); | |
382 | return (ProcXGetDeviceProperty(client)); | |
383 | } | |
384 | ||
385 | @@ -1253,11 +1252,10 @@ int | |
386 | SProcXIListProperties(ClientPtr client) | |
387 | { | |
388 | REQUEST(xXIListPropertiesReq); | |
389 | + REQUEST_SIZE_MATCH(xXIListPropertiesReq); | |
390 | ||
391 | swaps(&stuff->length); | |
392 | swaps(&stuff->deviceid); | |
393 | - | |
394 | - REQUEST_SIZE_MATCH(xXIListPropertiesReq); | |
395 | return (ProcXIListProperties(client)); | |
396 | } | |
397 | ||
398 | @@ -1279,11 +1277,11 @@ int | |
399 | SProcXIDeleteProperty(ClientPtr client) | |
400 | { | |
401 | REQUEST(xXIDeletePropertyReq); | |
402 | + REQUEST_SIZE_MATCH(xXIDeletePropertyReq); | |
403 | ||
404 | swaps(&stuff->length); | |
405 | swaps(&stuff->deviceid); | |
406 | swapl(&stuff->property); | |
407 | - REQUEST_SIZE_MATCH(xXIDeletePropertyReq); | |
408 | return (ProcXIDeleteProperty(client)); | |
409 | } | |
410 | ||
411 | @@ -1291,6 +1289,7 @@ int | |
412 | SProcXIGetProperty(ClientPtr client) | |
413 | { | |
414 | REQUEST(xXIGetPropertyReq); | |
415 | + REQUEST_SIZE_MATCH(xXIGetPropertyReq); | |
416 | ||
417 | swaps(&stuff->length); | |
418 | swaps(&stuff->deviceid); | |
419 | @@ -1298,7 +1297,6 @@ SProcXIGetProperty(ClientPtr client) | |
420 | swapl(&stuff->type); | |
421 | swapl(&stuff->offset); | |
422 | swapl(&stuff->len); | |
423 | - REQUEST_SIZE_MATCH(xXIGetPropertyReq); | |
424 | return (ProcXIGetProperty(client)); | |
425 | } | |
426 | ||
427 | diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c | |
428 | index 4e544f0..67a9a4f 100644 | |
429 | --- a/Xi/xiquerydevice.c | |
430 | +++ b/Xi/xiquerydevice.c | |
431 | @@ -54,6 +54,7 @@ int | |
432 | SProcXIQueryDevice(ClientPtr client) | |
433 | { | |
434 | REQUEST(xXIQueryDeviceReq); | |
435 | + REQUEST_SIZE_MATCH(xXIQueryDeviceReq); | |
436 | ||
437 | swaps(&stuff->length); | |
438 | swaps(&stuff->deviceid); | |
439 | diff --git a/Xi/xiquerypointer.c b/Xi/xiquerypointer.c | |
440 | index e9bdd42..7ec0c85 100644 | |
441 | --- a/Xi/xiquerypointer.c | |
442 | +++ b/Xi/xiquerypointer.c | |
443 | @@ -63,6 +63,8 @@ int | |
444 | SProcXIQueryPointer(ClientPtr client) | |
445 | { | |
446 | REQUEST(xXIQueryPointerReq); | |
447 | + REQUEST_SIZE_MATCH(xXIQueryPointerReq); | |
448 | + | |
449 | swaps(&stuff->length); | |
450 | swaps(&stuff->deviceid); | |
451 | swapl(&stuff->win); | |
452 | diff --git a/Xi/xiselectev.c b/Xi/xiselectev.c | |
453 | index 45a996e..168579f 100644 | |
454 | --- a/Xi/xiselectev.c | |
455 | +++ b/Xi/xiselectev.c | |
456 | @@ -114,6 +114,7 @@ int | |
457 | SProcXISelectEvents(ClientPtr client) | |
458 | { | |
459 | int i; | |
460 | + int len; | |
461 | xXIEventMask *evmask; | |
462 | ||
463 | REQUEST(xXISelectEventsReq); | |
464 | @@ -122,10 +123,17 @@ SProcXISelectEvents(ClientPtr client) | |
465 | swapl(&stuff->win); | |
466 | swaps(&stuff->num_masks); | |
467 | ||
468 | + len = stuff->length - bytes_to_int32(sizeof(xXISelectEventsReq)); | |
469 | evmask = (xXIEventMask *) &stuff[1]; | |
470 | for (i = 0; i < stuff->num_masks; i++) { | |
471 | + if (len < bytes_to_int32(sizeof(xXIEventMask))) | |
472 | + return BadLength; | |
473 | + len -= bytes_to_int32(sizeof(xXIEventMask)); | |
474 | swaps(&evmask->deviceid); | |
475 | swaps(&evmask->mask_len); | |
476 | + if (len < evmask->mask_len) | |
477 | + return BadLength; | |
478 | + len -= evmask->mask_len; | |
479 | evmask = | |
480 | (xXIEventMask *) (((char *) &evmask[1]) + evmask->mask_len * 4); | |
481 | } | |
482 | diff --git a/Xi/xisetclientpointer.c b/Xi/xisetclientpointer.c | |
483 | index 38ff51e..24d4a53 100644 | |
484 | --- a/Xi/xisetclientpointer.c | |
485 | +++ b/Xi/xisetclientpointer.c | |
486 | @@ -51,10 +51,11 @@ int | |
487 | SProcXISetClientPointer(ClientPtr client) | |
488 | { | |
489 | REQUEST(xXISetClientPointerReq); | |
490 | + REQUEST_SIZE_MATCH(xXISetClientPointerReq); | |
491 | + | |
492 | swaps(&stuff->length); | |
493 | swapl(&stuff->win); | |
494 | swaps(&stuff->deviceid); | |
495 | - REQUEST_SIZE_MATCH(xXISetClientPointerReq); | |
496 | return (ProcXISetClientPointer(client)); | |
497 | } | |
498 | ||
499 | diff --git a/Xi/xisetdevfocus.c b/Xi/xisetdevfocus.c | |
500 | index 372ec24..96a9a16 100644 | |
501 | --- a/Xi/xisetdevfocus.c | |
502 | +++ b/Xi/xisetdevfocus.c | |
503 | @@ -44,6 +44,8 @@ int | |
504 | SProcXISetFocus(ClientPtr client) | |
505 | { | |
506 | REQUEST(xXISetFocusReq); | |
507 | + REQUEST_AT_LEAST_SIZE(xXISetFocusReq); | |
508 | + | |
509 | swaps(&stuff->length); | |
510 | swaps(&stuff->deviceid); | |
511 | swapl(&stuff->focus); | |
512 | @@ -56,6 +58,8 @@ int | |
513 | SProcXIGetFocus(ClientPtr client) | |
514 | { | |
515 | REQUEST(xXIGetFocusReq); | |
516 | + REQUEST_AT_LEAST_SIZE(xXIGetFocusReq); | |
517 | + | |
518 | swaps(&stuff->length); | |
519 | swaps(&stuff->deviceid); | |
520 | ||
521 | diff --git a/Xi/xiwarppointer.c b/Xi/xiwarppointer.c | |
522 | index 3f051f7..780758a 100644 | |
523 | --- a/Xi/xiwarppointer.c | |
524 | +++ b/Xi/xiwarppointer.c | |
525 | @@ -56,6 +56,8 @@ int | |
526 | SProcXIWarpPointer(ClientPtr client) | |
527 | { | |
528 | REQUEST(xXIWarpPointerReq); | |
529 | + REQUEST_SIZE_MATCH(xXIWarpPointerReq); | |
530 | + | |
531 | swaps(&stuff->length); | |
532 | swapl(&stuff->src_win); | |
533 | swapl(&stuff->dst_win); | |
534 | diff --git a/include/dix.h b/include/dix.h | |
535 | index e0c6ed8..21176a8 100644 | |
536 | --- a/include/dix.h | |
537 | +++ b/include/dix.h | |
538 | @@ -74,6 +74,10 @@ SOFTWARE. | |
539 | if ((sizeof(req) >> 2) > client->req_len )\ | |
540 | return(BadLength) | |
541 | ||
542 | +#define REQUEST_AT_LEAST_EXTRA_SIZE(req, extra) \ | |
543 | + if (((sizeof(req) + ((uint64_t) extra)) >> 2) > client->req_len ) \ | |
544 | + return(BadLength) | |
545 | + | |
546 | #define REQUEST_FIXED_SIZE(req, n)\ | |
547 | if (((sizeof(req) >> 2) > client->req_len) || \ | |
548 | ((n >> 2) >= client->req_len) || \ | |
549 | -- | |
550 | 1.7.9.2 | |
551 |