107 lines
3.5 KiB
Diff
107 lines
3.5 KiB
Diff
From 62b9b6f86421ac7afc7cfe7b1627a8ec2a3c4874 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>
|
|
[Retrieved from
|
|
https://gitlab.freedesktop.org/wayland/wayland/-/commit/b19488c7154b902354cb26a27f11415d7799b0b2]
|
|
Signed-off-by: Quentin Schulz <quentin.schulz@theobroma-systems.com>
|
|
---
|
|
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 9bf8cb7..35dc40e 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 5d28531..c712f03 100644
|
|
--- a/src/wayland-util.c
|
|
+++ b/src/wayland-util.c
|
|
@@ -196,6 +196,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;
|
|
@@ -216,10 +217,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
|
|
@@ -236,6 +252,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;
|
|
@@ -274,8 +293,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) {
|
|
errno = EINVAL;
|
|
return -1;
|
|
--
|
|
2.38.1
|
|
|