]> git.sur5r.net Git - i3/i3/commitdiff
inject_randr1.5: Intercept X11 error responses in addition to replies
authorVladimir Panteleev <git@thecybershadow.net>
Tue, 12 Sep 2017 08:39:15 +0000 (08:39 +0000)
committerMichael Stapelberg <michael@stapelberg.de>
Wed, 13 Sep 2017 16:45:46 +0000 (18:45 +0200)
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

index 955df1e5474690d333a906534ae3b5e5f78bcaf5..6cccfa762d1a09b12a9704711d5c25fbcdadcc9b 100644 (file)
@@ -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,29 +331,12 @@ 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;
             }
+            /* END 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));
-                    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;
-                }
+            if (handle_sequence(connstate, sequence)) {
+                free(packet);
+                return;
             }
-            /* END RandR 1.5 specific */
 
             break;