11b5d61b8Smrg/* 21b5d61b8Smrg * Copyright © 2017 Broadcom 31b5d61b8Smrg * 41b5d61b8Smrg * Permission is hereby granted, free of charge, to any person obtaining a 51b5d61b8Smrg * copy of this software and associated documentation files (the "Software"), 61b5d61b8Smrg * to deal in the Software without restriction, including without limitation 71b5d61b8Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 81b5d61b8Smrg * and/or sell copies of the Software, and to permit persons to whom the 91b5d61b8Smrg * Software is furnished to do so, subject to the following conditions: 101b5d61b8Smrg * 111b5d61b8Smrg * The above copyright notice and this permission notice (including the next 121b5d61b8Smrg * paragraph) shall be included in all copies or substantial portions of the 131b5d61b8Smrg * Software. 141b5d61b8Smrg * 151b5d61b8Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 161b5d61b8Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 171b5d61b8Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 181b5d61b8Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 191b5d61b8Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 201b5d61b8Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 211b5d61b8Smrg * IN THE SOFTWARE. 221b5d61b8Smrg */ 231b5d61b8Smrg 241b5d61b8Smrg#include <unistd.h> 251b5d61b8Smrg#include <stdlib.h> 261b5d61b8Smrg#include <poll.h> 271b5d61b8Smrg#include <xcb/xcb.h> 281b5d61b8Smrg#include <xcb/bigreq.h> 291b5d61b8Smrg#include <xcb/xinput.h> 301b5d61b8Smrg 311b5d61b8Smrgint main(int argc, char **argv) 321b5d61b8Smrg{ 331b5d61b8Smrg xcb_connection_t *c = xcb_connect(NULL, NULL); 341b5d61b8Smrg int fd = xcb_get_file_descriptor(c); 351b5d61b8Smrg 361b5d61b8Smrg struct { 371b5d61b8Smrg uint8_t extension; 381b5d61b8Smrg uint8_t opcode; 391b5d61b8Smrg uint16_t length; 401b5d61b8Smrg uint32_t length_bigreq; 411b5d61b8Smrg uint32_t win; 421b5d61b8Smrg int num_masks; 431b5d61b8Smrg uint16_t pad; 441b5d61b8Smrg } xise_req = { 451b5d61b8Smrg .extension = 0, 461b5d61b8Smrg .opcode = XCB_INPUT_XI_SELECT_EVENTS, 471b5d61b8Smrg /* The server triggers BadValue on a zero num_mask */ 481b5d61b8Smrg .num_masks = 0, 491b5d61b8Smrg .win = 0, 501b5d61b8Smrg 511b5d61b8Smrg /* This is the value that triggers the bug. */ 521b5d61b8Smrg .length_bigreq = 0, 531b5d61b8Smrg }; 541b5d61b8Smrg 551b5d61b8Smrg xcb_query_extension_cookie_t cookie; 561b5d61b8Smrg xcb_query_extension_reply_t *rep; 571b5d61b8Smrg 581b5d61b8Smrg cookie = xcb_query_extension(c, 15, "XInputExtension"); 591b5d61b8Smrg rep = xcb_query_extension_reply(c, cookie, NULL); 601b5d61b8Smrg xise_req.extension = rep->major_opcode; 611b5d61b8Smrg 621b5d61b8Smrg free(xcb_big_requests_enable_reply(c, xcb_big_requests_enable(c), NULL)); 631b5d61b8Smrg 641b5d61b8Smrg /* Manually write out the bad request. XCB can't help us here.*/ 651b5d61b8Smrg write(fd, &xise_req, sizeof(xise_req)); 661b5d61b8Smrg 671b5d61b8Smrg /* Block until the server has processed our mess and throws an 681b5d61b8Smrg * error. If we get disconnected, then the server has noticed what we're 691b5d61b8Smrg * up to. If we get an error back from the server, it looked at our fake 701b5d61b8Smrg * request - which shouldn't happen. 711b5d61b8Smrg */ 721b5d61b8Smrg struct pollfd pfd = { 731b5d61b8Smrg .fd = fd, 741b5d61b8Smrg .events = POLLIN, 751b5d61b8Smrg }; 761b5d61b8Smrg poll(&pfd, 1, -1); 771b5d61b8Smrg 781b5d61b8Smrg if (pfd.revents & POLLHUP) { 791b5d61b8Smrg /* We got killed by the server for being naughty. Yay! */ 801b5d61b8Smrg return 0; 811b5d61b8Smrg } 821b5d61b8Smrg 831b5d61b8Smrg /* We didn't get disconnected, that's bad. If we get a BadValue from our 841b5d61b8Smrg * request, we at least know that the bug triggered. 851b5d61b8Smrg * 861b5d61b8Smrg * If we get anything else back, something else has gone wrong. 871b5d61b8Smrg */ 881b5d61b8Smrg xcb_generic_error_t error; 891b5d61b8Smrg int r = read(fd, &error, sizeof(error)); 901b5d61b8Smrg 911b5d61b8Smrg if (r == sizeof(error) && 921b5d61b8Smrg error.error_code == 2 /* BadValue */ && 931b5d61b8Smrg error.major_code == xise_req.extension && 941b5d61b8Smrg error.minor_code == XCB_INPUT_XI_SELECT_EVENTS) 951b5d61b8Smrg return 1; /* Our request was processed, which shouldn't happen */ 961b5d61b8Smrg 971b5d61b8Smrg /* Something else bad happened. We got something back but it's not the 981b5d61b8Smrg * error we expected. If this happens, it needs to be investigated. */ 991b5d61b8Smrg 1001b5d61b8Smrg return 2; 1011b5d61b8Smrg} 102