107 lines
3.4 KiB
Diff
107 lines
3.4 KiB
Diff
From b19488c7154b902354cb26a27f11415d7799b0b2 Mon Sep 17 00:00:00 2001
|
|
From: Derek Foreman <derek.foreman@collabora.com>
|
|
Date: Fri, 28 Jan 2022 13:18:37 -0600
|
|
Subject: [PATCH] util: Limit size of wl_map
|
|
|
|
Since server IDs are basically indistinguishable from really big client
|
|
IDs at many points in the source, it's theoretically possible to overflow
|
|
a map and either overflow server IDs into the client ID space, or grow
|
|
client IDs into the server ID space. This would currently take a massive
|
|
amount of RAM, but the definition of massive changes yearly.
|
|
|
|
Prevent this by placing a ridiculous but arbitrary upper bound on the
|
|
number of items we can put in a map: 0xF00000, somewhere over 15 million.
|
|
This should satisfy pathological clients without restriction, but stays
|
|
well clear of the 0xFF000000 transition point between server and client
|
|
IDs. It will still take an improbable amount of RAM to hit this, and a
|
|
client could still exhaust all RAM in this way, but our goal is to prevent
|
|
overflow and undefined behaviour.
|
|
|
|
Fixes #224
|
|
|
|
Signed-off-by: Derek Foreman <derek.foreman@collabora.com>
|
|
|
|
Conflict:NA
|
|
Reference:https://gitlab.freedesktop.org/wayland/wayland/-/commit/b19488c7154b902354cb26a27f11415d7799b0b2
|
|
---
|
|
src/wayland-private.h | 1 +
|
|
src/wayland-util.c | 25 +++++++++++++++++++++++--
|
|
2 files changed, 24 insertions(+), 2 deletions(-)
|
|
|
|
diff --git a/src/wayland-private.h b/src/wayland-private.h
|
|
index 210451e..9274f1b 100644
|
|
--- a/src/wayland-private.h
|
|
+++ b/src/wayland-private.h
|
|
@@ -45,6 +45,7 @@
|
|
#define WL_MAP_SERVER_SIDE 0
|
|
#define WL_MAP_CLIENT_SIDE 1
|
|
#define WL_SERVER_ID_START 0xff000000
|
|
+#define WL_MAP_MAX_OBJECTS 0x00f00000
|
|
#define WL_CLOSURE_MAX_ARGS 20
|
|
|
|
struct wl_object {
|
|
diff --git a/src/wayland-util.c b/src/wayland-util.c
|
|
index c89a67b..997a2c7 100644
|
|
--- a/src/wayland-util.c
|
|
+++ b/src/wayland-util.c
|
|
@@ -197,6 +197,7 @@ wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
|
|
union map_entry *start, *entry;
|
|
struct wl_array *entries;
|
|
uint32_t base;
|
|
+ uint32_t count;
|
|
|
|
if (map->side == WL_MAP_CLIENT_SIDE) {
|
|
entries = &map->client_entries;
|
|
@@ -217,10 +218,25 @@ wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
|
|
start = entries->data;
|
|
}
|
|
|
|
+ /* wl_array only grows, so if we have too many objects at
|
|
+ * this point there's no way to clean up. We could be more
|
|
+ * pro-active about trying to avoid this allocation, but
|
|
+ * it doesn't really matter because at this point there is
|
|
+ * nothing to be done but disconnect the client and delete
|
|
+ * the whole array either way.
|
|
+ */
|
|
+ count = entry - start;
|
|
+ if (count > WL_MAP_MAX_OBJECTS) {
|
|
+ /* entry->data is freshly malloced garbage, so we'd
|
|
+ * better make it a NULL so wl_map_for_each doesn't
|
|
+ * dereference it later. */
|
|
+ entry->data = NULL;
|
|
+ return 0;
|
|
+ }
|
|
entry->data = data;
|
|
entry->next |= (flags & 0x1) << 1;
|
|
|
|
- return (entry - start) + base;
|
|
+ return count + base;
|
|
}
|
|
|
|
int
|
|
@@ -237,6 +253,9 @@ wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data)
|
|
i -= WL_SERVER_ID_START;
|
|
}
|
|
|
|
+ if (i > WL_MAP_MAX_OBJECTS)
|
|
+ return -1;
|
|
+
|
|
count = entries->size / sizeof *start;
|
|
if (count < i)
|
|
return -1;
|
|
@@ -271,8 +290,10 @@ wl_map_reserve_new(struct wl_map *map, uint32_t i)
|
|
i -= WL_SERVER_ID_START;
|
|
}
|
|
|
|
- count = entries->size / sizeof *start;
|
|
+ if (i > WL_MAP_MAX_OBJECTS)
|
|
+ return -1;
|
|
|
|
+ count = entries->size / sizeof *start;
|
|
if (count < i)
|
|
return -1;
|
|
|
|
--
|
|
2.33.0
|
|
|