From 7fb027ad376039431b74eb2f5708d6f9ef3cc7de Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Tue, 12 Sep 2017 08:39:15 +0000 Subject: [PATCH] inject_randr1.5: Intercept X11 error responses in addition to replies Allow clients to send garbage to the server, then intercept the server's error response and substitute it with the supplied simulated reply data. --- testcases/inject_randr1.5.c | 62 +++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/testcases/inject_randr1.5.c b/testcases/inject_randr1.5.c index 955df1e5..6cccfa76 100644 --- a/testcases/inject_randr1.5.c +++ b/testcases/inject_randr1.5.c @@ -276,6 +276,32 @@ static void read_client_x11_packet_cb(EV_P_ ev_io *w, int revents) { free(request); } +static bool handle_sequence(struct connstate *connstate, uint16_t sequence) { + /* BEGIN RandR 1.5 specific */ + if (sequence == connstate->getmonitors) { + printf("RRGetMonitors reply!\n"); + if (getmonitors_reply.buf != NULL) { + printf("injecting reply\n"); + ((generic_x11_reply_t *)getmonitors_reply.buf)->sequence = sequence; + must_write(writeall(connstate->clientw->fd, getmonitors_reply.buf, getmonitors_reply.len)); + return true; + } + } + + if (sequence == connstate->getoutputinfo) { + printf("RRGetOutputInfo reply!\n"); + if (getoutputinfo_reply.buf != NULL) { + printf("injecting reply\n"); + ((generic_x11_reply_t *)getoutputinfo_reply.buf)->sequence = sequence; + must_write(writeall(connstate->clientw->fd, getoutputinfo_reply.buf, getoutputinfo_reply.len)); + return true; + } + } + /* END RandR 1.5 specific */ + + return false; +} + static void read_server_x11_packet_cb(EV_P_ ev_io *w, int revents) { struct connstate *connstate = (struct connstate *)w->data; // all packets from the server are at least 32 bytes in length @@ -283,9 +309,14 @@ static void read_server_x11_packet_cb(EV_P_ ev_io *w, int revents) { void *packet = smalloc(len); must_read(readall_into(packet, len, connstate->serverw->fd)); switch (((generic_x11_reply_t *)packet)->code) { - case 0: // error + case 0: { // error + const uint16_t sequence = ((xcb_request_error_t *)packet)->sequence; + if (handle_sequence(connstate, sequence)) { + free(packet); + return; + } break; - + } case 1: // reply len += ((generic_x11_reply_t *)packet)->length * 4; if (len > 32) { @@ -300,30 +331,13 @@ static void read_server_x11_packet_cb(EV_P_ ev_io *w, int revents) { xcb_query_extension_reply_t *reply = packet; connstate->randr_major_opcode = reply->major_opcode; } - - if (sequence == connstate->getmonitors) { - printf("RRGetMonitors reply!\n"); - if (getmonitors_reply.buf != NULL) { - printf("injecting reply\n"); - ((generic_x11_reply_t *)getmonitors_reply.buf)->sequence = sequence; - must_write(writeall(connstate->clientw->fd, getmonitors_reply.buf, getmonitors_reply.len)); - free(packet); - return; - } - } - - if (sequence == connstate->getoutputinfo) { - printf("RRGetOutputInfo reply!\n"); - if (getoutputinfo_reply.buf != NULL) { - printf("injecting reply\n"); - ((generic_x11_reply_t *)getoutputinfo_reply.buf)->sequence = sequence; - must_write(writeall(connstate->clientw->fd, getoutputinfo_reply.buf, getoutputinfo_reply.len)); - free(packet); - return; - } - } /* END RandR 1.5 specific */ + if (handle_sequence(connstate, sequence)) { + free(packet); + return; + } + break; default: // event