From 11623e8fddb924c7ae317f2eabac23785ae5e8d5 Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Mon, 22 Jul 2019 15:58:49 +0200 Subject: [PATCH] =?utf8?q?wayland-shm:=20Don=E2=80=99t=20set=20SIGBUS=20ha?= =?utf8?q?ndlers=20on=20unshrinkable=20fd?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit If a client set the F_SEAL_SHRINK seal on the fd before passing it to the compositor, the kernel will ensure this fd won’t be able to shrink, ever. This allows us to avoid setting up the SIGBUS handlers on such file descriptors. Signed-off-by: Emmanuel Gil Peyrot --- src/wayland-shm.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/wayland-shm.c b/src/wayland-shm.c index 967b875..b85e5a7 100644 --- a/src/wayland-shm.c +++ b/src/wayland-shm.c @@ -30,6 +30,8 @@ #define _GNU_SOURCE +#include "config.h" + #include #include #include @@ -41,6 +43,7 @@ #include #include #include +#include #include "wayland-util.h" #include "wayland-private.h" @@ -60,6 +63,7 @@ struct wl_shm_pool { char *data; int32_t size; int32_t new_size; + bool sigbus_is_impossible; }; struct wl_shm_buffer { @@ -259,6 +263,7 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, uint32_t id, int fd, int32_t size) { struct wl_shm_pool *pool; + int seals; if (size <= 0) { wl_resource_post_error(resource, @@ -273,6 +278,15 @@ shm_create_pool(struct wl_client *client, struct wl_resource *resource, goto err_close; } +#ifdef HAVE_MEMFD_CREATE + seals = fcntl(fd, F_GET_SEALS); + if (seals == -1) + seals = 0; + pool->sigbus_is_impossible = (seals & F_SEAL_SHRINK) ? true : false; +#else + pool->sigbus_is_impossible = false; +#endif + pool->internal_refcount = 1; pool->external_refcount = 0; pool->size = size; @@ -571,6 +585,9 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer) struct wl_shm_pool *pool = buffer->pool; struct wl_shm_sigbus_data *sigbus_data; + if (pool->sigbus_is_impossible) + return; + pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key); sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key); @@ -603,9 +620,13 @@ wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer) WL_EXPORT void wl_shm_buffer_end_access(struct wl_shm_buffer *buffer) { - struct wl_shm_sigbus_data *sigbus_data = - pthread_getspecific(wl_shm_sigbus_data_key); + struct wl_shm_pool *pool = buffer->pool; + struct wl_shm_sigbus_data *sigbus_data; + if (pool->sigbus_is_impossible) + return; + + sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key); assert(sigbus_data && sigbus_data->access_count >= 1); if (--sigbus_data->access_count == 0) { -- 2.7.4