mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-10-29 05:40:16 -04:00
wayland-shm: Don’t set SIGBUS handlers on unshrinkable fd
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 <linkmauve@linkmauve.fr>
This commit is contained in:
parent
d5055ad913
commit
11623e8fdd
1 changed files with 23 additions and 2 deletions
|
|
@ -30,6 +30,8 @@
|
|||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
|
@ -41,6 +43,7 @@
|
|||
#include <signal.h>
|
||||
#include <pthread.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue