wayland-server: Verify request versions before invoking handler
authorJason Ekstrand <jason@jlekstrand.net>
Tue, 2 Jul 2013 18:57:10 +0000 (14:57 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 2 Jul 2013 21:01:46 +0000 (17:01 -0400)
This commit provides a layer of protection for the compositor in the form
of message version checking.  We track version information in the
wl_resource and now use this version information to verify that a request
exists in that protocol version before invoking it.  This way libwayland
won't accidentally invoke a request that does not exist and thereby cause
the compositor to crash.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
src/wayland-server.c

index 57770ab..bdacaee 100644 (file)
@@ -211,6 +211,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
        struct wl_closure *closure;
        const struct wl_message *message;
        uint32_t p[2];
+       uint32_t resource_flags;
        int opcode, size;
        int len;
 
@@ -247,6 +248,7 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
                        break;
 
                resource = wl_map_lookup(&client->objects, p[0]);
+               resource_flags = wl_map_lookup_flags(&client->objects, p[0]);
                if (resource == NULL) {
                        wl_resource_post_error(client->display_resource,
                                               WL_DISPLAY_ERROR_INVALID_OBJECT,
@@ -266,6 +268,19 @@ wl_client_connection_data(int fd, uint32_t mask, void *data)
                }
 
                message = &object->interface->methods[opcode];
+               if (!(resource_flags & WL_MAP_ENTRY_LEGACY) &&
+                   resource->version > 0 &&
+                   resource->version < wl_message_get_since(message)) {
+                       wl_resource_post_error(client->display_resource,
+                                              WL_DISPLAY_ERROR_INVALID_METHOD,
+                                              "invalid method %d, object %s@%u",
+                                              opcode,
+                                              object->interface->name,
+                                              object->id);
+                       break;
+               }
+
+
                closure = wl_connection_demarshal(client->connection, size,
                                                  &client->objects, message);
                len -= size;