diff options
Diffstat (limited to 'use-memfd.patch')
-rw-r--r-- | use-memfd.patch | 790 |
1 files changed, 790 insertions, 0 deletions
diff --git a/use-memfd.patch b/use-memfd.patch new file mode 100644 index 0000000..9a8e899 --- /dev/null +++ b/use-memfd.patch @@ -0,0 +1,790 @@ +From 31e75c3e5c4f59b603602420d2708588091a07b2 Mon Sep 17 00:00:00 2001 +From: Ray Strode <rstrode@redhat.com> +Date: Wed, 20 Jan 2016 12:22:29 -0500 +Subject: [PATCH 1/6] wayland: unlink shm file earlier in create function + +create_shm_pool unlinks the temporary file a little, +too late. It should be unlinked before ftruncate() +is called for two reasons: + +1) if ftruncate fails, the file is currently not +getting cleaned up at all +2) in theory, if the file is public some other process +could muck with it + +This commit just moves the unlink call a little higher +up. + +https://bugzilla.gnome.org/show_bug.cgi?id=760897 +--- + gdk/wayland/gdkdisplay-wayland.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index 97eebca..2f0c64e 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -914,73 +914,73 @@ buffer_release_callback (void *_data, + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + + data->busy = FALSE; + cairo_surface_destroy (surface); + } + + static const struct wl_buffer_listener buffer_listener = { + buffer_release_callback + }; + + static struct wl_shm_pool * + create_shm_pool (struct wl_shm *shm, + int width, + int height, + size_t *buf_length, + void **data_out) + { + char filename[] = "/tmp/wayland-shm-XXXXXX"; + struct wl_shm_pool *pool; + int fd, size, stride; + void *data; + + fd = mkstemp (filename); + if (fd < 0) + { + g_critical (G_STRLOC ": Unable to create temporary file (%s): %s", + filename, g_strerror (errno)); + return NULL; + } ++ unlink (filename); + + stride = width * 4; + size = stride * height; + if (ftruncate (fd, size) < 0) + { + g_critical (G_STRLOC ": Truncating temporary file failed: %s", + g_strerror (errno)); + close (fd); + return NULL; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); +- unlink (filename); + + if (data == MAP_FAILED) + { + g_critical (G_STRLOC ": mmap'ping temporary file failed: %s", + g_strerror (errno)); + close (fd); + return NULL; + } + + pool = wl_shm_create_pool (shm, fd, size); + + close (fd); + + *data_out = data; + *buf_length = size; + + return pool; + } + + static void + gdk_wayland_cairo_surface_destroy (void *p) + { + GdkWaylandCairoSurfaceData *data = p; + + if (data->buffer) + wl_buffer_destroy (data->buffer); + + if (data->pool) + wl_shm_pool_destroy (data->pool); + +-- +2.7.0 + + +From 743f5ef21afe0c00aa572d49d197658aa9613a01 Mon Sep 17 00:00:00 2001 +From: Ray Strode <rstrode@redhat.com> +Date: Wed, 20 Jan 2016 11:40:34 -0500 +Subject: [PATCH 2/6] wayland: clean up stride calculation when creating shm + surface + +Right now, we assume the stride for the image surface needs to +be 4 byte aligned. This is, in fact, true, but it's better to +ask cairo for the alignment requirement directly rather than +assume we know the alignment rules. + +This commit changes the code to use cairo_format_stride_for_width +to calculate a suitable rowstride for pixman. + +https://bugzilla.gnome.org/show_bug.cgi?id=760897 +--- + gdk/wayland/gdkdisplay-wayland.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index 2f0c64e..bf3c20c 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -978,76 +978,76 @@ gdk_wayland_cairo_surface_destroy (void *p) + { + GdkWaylandCairoSurfaceData *data = p; + + if (data->buffer) + wl_buffer_destroy (data->buffer); + + if (data->pool) + wl_shm_pool_destroy (data->pool); + + munmap (data->buf, data->buf_length); + g_free (data); + } + + cairo_surface_t * + _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display, + int width, + int height, + guint scale) + { + GdkWaylandCairoSurfaceData *data; + cairo_surface_t *surface = NULL; + cairo_status_t status; + int stride; + + data = g_new (GdkWaylandCairoSurfaceData, 1); + data->display = display; + data->buffer = NULL; + data->scale = scale; + data->busy = FALSE; + +- stride = width * 4; ++ stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width*scale); + + data->pool = create_shm_pool (display->shm, + width*scale, height*scale, + &data->buf_length, + &data->buf); + + surface = cairo_image_surface_create_for_data (data->buf, + CAIRO_FORMAT_ARGB32, + width*scale, + height*scale, +- stride*scale); ++ stride); + + data->buffer = wl_shm_pool_create_buffer (data->pool, 0, + width*scale, height*scale, +- stride*scale, WL_SHM_FORMAT_ARGB8888); ++ stride, WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener (data->buffer, &buffer_listener, surface); + + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key, + data, gdk_wayland_cairo_surface_destroy); + + cairo_surface_set_device_scale (surface, scale, scale); + + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) + { + g_critical (G_STRLOC ": Unable to create Cairo image surface: %s", + cairo_status_to_string (status)); + } + + return surface; + } + + struct wl_buffer * + _gdk_wayland_shm_surface_get_wl_buffer (cairo_surface_t *surface) + { + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + return data->buffer; + } + + void + _gdk_wayland_shm_surface_set_busy (cairo_surface_t *surface) + { + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + data->busy = TRUE; + cairo_surface_reference (surface); +-- +2.7.0 + + +From 2e704d3c0f7daaf38701d341186178c2adc442d1 Mon Sep 17 00:00:00 2001 +From: Ray Strode <rstrode@redhat.com> +Date: Wed, 20 Jan 2016 12:35:44 -0500 +Subject: [PATCH 3/6] wayland: don't pass in width and height to + create_shm_pool + +create_shm_pool doesn't need the width or height, it just needs +the total size. By passing it in, we're requiring it to redo +stride calculation unnecessarily. + +This commit drops the width and height parameters and makes the +function just take the total size directly. + +https://bugzilla.gnome.org/show_bug.cgi?id=760897 +--- + gdk/wayland/gdkdisplay-wayland.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index bf3c20c..7c19a5c 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -897,81 +897,78 @@ gdk_wayland_display_get_xdg_shell (GdkDisplay *display) + + static const cairo_user_data_key_t gdk_wayland_cairo_key; + + typedef struct _GdkWaylandCairoSurfaceData { + gpointer buf; + size_t buf_length; + struct wl_shm_pool *pool; + struct wl_buffer *buffer; + GdkWaylandDisplay *display; + uint32_t scale; + gboolean busy; + } GdkWaylandCairoSurfaceData; + + static void + buffer_release_callback (void *_data, + struct wl_buffer *wl_buffer) + { + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + + data->busy = FALSE; + cairo_surface_destroy (surface); + } + + static const struct wl_buffer_listener buffer_listener = { + buffer_release_callback + }; + + static struct wl_shm_pool * + create_shm_pool (struct wl_shm *shm, +- int width, +- int height, ++ int size, + size_t *buf_length, + void **data_out) + { + char filename[] = "/tmp/wayland-shm-XXXXXX"; + struct wl_shm_pool *pool; +- int fd, size, stride; ++ int fd; + void *data; + + fd = mkstemp (filename); + if (fd < 0) + { + g_critical (G_STRLOC ": Unable to create temporary file (%s): %s", + filename, g_strerror (errno)); + return NULL; + } + unlink (filename); + +- stride = width * 4; +- size = stride * height; + if (ftruncate (fd, size) < 0) + { + g_critical (G_STRLOC ": Truncating temporary file failed: %s", + g_strerror (errno)); + close (fd); + return NULL; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { + g_critical (G_STRLOC ": mmap'ping temporary file failed: %s", + g_strerror (errno)); + close (fd); + return NULL; + } + + pool = wl_shm_create_pool (shm, fd, size); + + close (fd); + + *data_out = data; + *buf_length = size; + + return pool; + } + + static void + gdk_wayland_cairo_surface_destroy (void *p) +@@ -981,61 +978,61 @@ gdk_wayland_cairo_surface_destroy (void *p) + if (data->buffer) + wl_buffer_destroy (data->buffer); + + if (data->pool) + wl_shm_pool_destroy (data->pool); + + munmap (data->buf, data->buf_length); + g_free (data); + } + + cairo_surface_t * + _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display, + int width, + int height, + guint scale) + { + GdkWaylandCairoSurfaceData *data; + cairo_surface_t *surface = NULL; + cairo_status_t status; + int stride; + + data = g_new (GdkWaylandCairoSurfaceData, 1); + data->display = display; + data->buffer = NULL; + data->scale = scale; + data->busy = FALSE; + + stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32, width*scale); + + data->pool = create_shm_pool (display->shm, +- width*scale, height*scale, ++ height*scale*stride, + &data->buf_length, + &data->buf); + + surface = cairo_image_surface_create_for_data (data->buf, + CAIRO_FORMAT_ARGB32, + width*scale, + height*scale, + stride); + + data->buffer = wl_shm_pool_create_buffer (data->pool, 0, + width*scale, height*scale, + stride, WL_SHM_FORMAT_ARGB8888); + wl_buffer_add_listener (data->buffer, &buffer_listener, surface); + + cairo_surface_set_user_data (surface, &gdk_wayland_cairo_key, + data, gdk_wayland_cairo_surface_destroy); + + cairo_surface_set_device_scale (surface, scale, scale); + + status = cairo_surface_status (surface); + if (status != CAIRO_STATUS_SUCCESS) + { + g_critical (G_STRLOC ": Unable to create Cairo image surface: %s", + cairo_status_to_string (status)); + } + + return surface; + } + + struct wl_buffer * +-- +2.7.0 + + +From 8717b4221f634e321aee80bc8accb60b6a24552d Mon Sep 17 00:00:00 2001 +From: Matthias Clasen <mclasen@redhat.com> +Date: Thu, 21 Jan 2016 22:53:06 -0500 +Subject: [PATCH 4/6] wayland: Don't hardcode /tmp + +As pointed out in https://bugzilla.gnome.org/show_bug.cgi?id=760964, +we should use the GLib facilities for determining the preferred +location for temporary files. +--- + gdk/wayland/gdkdisplay-wayland.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index 7c19a5c..5e88d96 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -901,95 +901,100 @@ typedef struct _GdkWaylandCairoSurfaceData { + gpointer buf; + size_t buf_length; + struct wl_shm_pool *pool; + struct wl_buffer *buffer; + GdkWaylandDisplay *display; + uint32_t scale; + gboolean busy; + } GdkWaylandCairoSurfaceData; + + static void + buffer_release_callback (void *_data, + struct wl_buffer *wl_buffer) + { + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + + data->busy = FALSE; + cairo_surface_destroy (surface); + } + + static const struct wl_buffer_listener buffer_listener = { + buffer_release_callback + }; + + static struct wl_shm_pool * + create_shm_pool (struct wl_shm *shm, + int size, + size_t *buf_length, + void **data_out) + { +- char filename[] = "/tmp/wayland-shm-XXXXXX"; ++ char *filename; + struct wl_shm_pool *pool; + int fd; + void *data; + ++ filename = g_strconcat (g_get_tmp_dir (), G_DIR_SEPARATOR_S, "wayland-shm-XXXXXX", NULL); + fd = mkstemp (filename); + if (fd < 0) + { + g_critical (G_STRLOC ": Unable to create temporary file (%s): %s", + filename, g_strerror (errno)); ++ g_free (filename); + return NULL; + } + unlink (filename); + + if (ftruncate (fd, size) < 0) + { +- g_critical (G_STRLOC ": Truncating temporary file failed: %s", +- g_strerror (errno)); ++ g_critical (G_STRLOC ": Truncating temporary file (%s) failed: %s", ++ filename, g_strerror (errno)); ++ g_free (filename); + close (fd); + return NULL; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { +- g_critical (G_STRLOC ": mmap'ping temporary file failed: %s", +- g_strerror (errno)); ++ g_critical (G_STRLOC ": mmap'ping temporary file (%s) failed: %s", ++ filename, g_strerror (errno)); ++ g_free (filename); + close (fd); + return NULL; + } + + pool = wl_shm_create_pool (shm, fd, size); + + close (fd); ++ g_free (filename); + + *data_out = data; + *buf_length = size; + + return pool; + } + + static void + gdk_wayland_cairo_surface_destroy (void *p) + { + GdkWaylandCairoSurfaceData *data = p; + + if (data->buffer) + wl_buffer_destroy (data->buffer); + + if (data->pool) + wl_shm_pool_destroy (data->pool); + + munmap (data->buf, data->buf_length); + g_free (data); + } + + cairo_surface_t * + _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display, + int width, + int height, + guint scale) + { + GdkWaylandCairoSurfaceData *data; + cairo_surface_t *surface = NULL; +-- +2.7.0 + + +From e9ba1539160378dbf484e5760c1e54ca0415f939 Mon Sep 17 00:00:00 2001 +From: Ray Strode <rstrode@redhat.com> +Date: Mon, 25 Jan 2016 11:41:23 -0500 +Subject: [PATCH 5/6] wayland: use memfd_create instead of open in tmpdir + +The tmpdir is used for a wide assortment of things, and +can easily fill up. If it fills then desktop will start +crashing with SIGBUS errors. + +This commit changes the shm pool allocation code, to use +memfd_create, instead, so the shared memory files will +be anonymous and not associated with /tmp + +https://bugzilla.gnome.org/show_bug.cgi?id=761095 +--- + gdk/wayland/gdkdisplay-wayland.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index 5e88d96..360c489 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -1,55 +1,57 @@ + /* + * Copyright © 2010 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see <http://www.gnu.org/licenses/>. + */ + + #include "config.h" + + #include <stdlib.h> + #include <string.h> + #include <errno.h> + #include <unistd.h> + #include <fcntl.h> ++#include <linux/memfd.h> + #include <sys/mman.h> ++#include <sys/syscall.h> + + #include <glib.h> + #include "gdkwayland.h" + #include "gdkdisplay.h" + #include "gdkdisplay-wayland.h" + #include "gdkscreen.h" + #include "gdkinternals.h" + #include "gdkdeviceprivate.h" + #include "gdkdevicemanager.h" + #include "gdkkeysprivate.h" + #include "gdkprivate-wayland.h" + #include "gdkglcontext-wayland.h" + #include "pointer-gestures-unstable-v1-client-protocol.h" + + /** + * SECTION:wayland_interaction + * @Short_description: Wayland backend-specific functions + * @Title: Wayland Interaction + * + * The functions in this section are specific to the GDK Wayland backend. + * To use them, you need to include the `<gdk/gdkwayland.h>` header and use + * the Wayland-specific pkg-config files to build your application (either + * `gdk-wayland-3.0` or `gtk+-wayland-3.0`). + * + * To make your code compile with other GDK backends, guard backend-specific + * calls by an ifdef as follows. Since GDK may be built with multiple + * backends, you should also check for the backend that is in use (e.g. by + * using the GDK_IS_WAYLAND_DISPLAY() macro). + * |[<!-- language="C" --> + * #ifdef GDK_WINDOWING_WAYLAND +@@ -901,100 +903,94 @@ typedef struct _GdkWaylandCairoSurfaceData { + gpointer buf; + size_t buf_length; + struct wl_shm_pool *pool; + struct wl_buffer *buffer; + GdkWaylandDisplay *display; + uint32_t scale; + gboolean busy; + } GdkWaylandCairoSurfaceData; + + static void + buffer_release_callback (void *_data, + struct wl_buffer *wl_buffer) + { + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + + data->busy = FALSE; + cairo_surface_destroy (surface); + } + + static const struct wl_buffer_listener buffer_listener = { + buffer_release_callback + }; + + static struct wl_shm_pool * + create_shm_pool (struct wl_shm *shm, + int size, + size_t *buf_length, + void **data_out) + { +- char *filename; + struct wl_shm_pool *pool; +- int fd; ++ int ret, fd; + void *data; + +- filename = g_strconcat (g_get_tmp_dir (), G_DIR_SEPARATOR_S, "wayland-shm-XXXXXX", NULL); +- fd = mkstemp (filename); +- if (fd < 0) ++ ret = syscall (SYS_memfd_create, "gdk-wayland", MFD_CLOEXEC); ++ ++ if (ret < 0) + { +- g_critical (G_STRLOC ": Unable to create temporary file (%s): %s", +- filename, g_strerror (errno)); +- g_free (filename); ++ g_critical (G_STRLOC ": creating shared memory file failed: %s", ++ g_strerror (-ret)); + return NULL; + } +- unlink (filename); ++ ++ fd = ret; + + if (ftruncate (fd, size) < 0) + { +- g_critical (G_STRLOC ": Truncating temporary file (%s) failed: %s", +- filename, g_strerror (errno)); +- g_free (filename); ++ g_critical (G_STRLOC ": Truncating shared memory file failed: %m"); + close (fd); + return NULL; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { +- g_critical (G_STRLOC ": mmap'ping temporary file (%s) failed: %s", +- filename, g_strerror (errno)); +- g_free (filename); ++ g_critical (G_STRLOC ": mmap'ping shared memory file failed: %m"); + close (fd); + return NULL; + } + + pool = wl_shm_create_pool (shm, fd, size); + + close (fd); +- g_free (filename); + + *data_out = data; + *buf_length = size; + + return pool; + } + + static void + gdk_wayland_cairo_surface_destroy (void *p) + { + GdkWaylandCairoSurfaceData *data = p; + + if (data->buffer) + wl_buffer_destroy (data->buffer); + + if (data->pool) + wl_shm_pool_destroy (data->pool); + + munmap (data->buf, data->buf_length); + g_free (data); + } + + cairo_surface_t * + _gdk_wayland_display_create_shm_surface (GdkWaylandDisplay *display, + int width, + int height, + guint scale) + { + GdkWaylandCairoSurfaceData *data; + cairo_surface_t *surface = NULL; +-- +2.7.0 + + +From ba8ce203ed2f1723b7f332fba1efb28f96f0a1c4 Mon Sep 17 00:00:00 2001 +From: Ray Strode <rstrode@redhat.com> +Date: Mon, 25 Jan 2016 13:55:25 -0500 +Subject: [PATCH 6/6] wayland: __NR_memfd_create instead of SYS_memfd_create + +It looks like the gnome-continuous headers haven't quite +caught up yet, so try __NR_memfd_create instead. + +If that doesn't work, i'll likely just add in a fallback +code path. +--- + gdk/wayland/gdkdisplay-wayland.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c +index 360c489..f200800 100644 +--- a/gdk/wayland/gdkdisplay-wayland.c ++++ b/gdk/wayland/gdkdisplay-wayland.c +@@ -907,61 +907,61 @@ typedef struct _GdkWaylandCairoSurfaceData { + GdkWaylandDisplay *display; + uint32_t scale; + gboolean busy; + } GdkWaylandCairoSurfaceData; + + static void + buffer_release_callback (void *_data, + struct wl_buffer *wl_buffer) + { + cairo_surface_t *surface = _data; + GdkWaylandCairoSurfaceData *data = cairo_surface_get_user_data (surface, &gdk_wayland_cairo_key); + + data->busy = FALSE; + cairo_surface_destroy (surface); + } + + static const struct wl_buffer_listener buffer_listener = { + buffer_release_callback + }; + + static struct wl_shm_pool * + create_shm_pool (struct wl_shm *shm, + int size, + size_t *buf_length, + void **data_out) + { + struct wl_shm_pool *pool; + int ret, fd; + void *data; + +- ret = syscall (SYS_memfd_create, "gdk-wayland", MFD_CLOEXEC); ++ ret = syscall (__NR_memfd_create, "gdk-wayland", MFD_CLOEXEC); + + if (ret < 0) + { + g_critical (G_STRLOC ": creating shared memory file failed: %s", + g_strerror (-ret)); + return NULL; + } + + fd = ret; + + if (ftruncate (fd, size) < 0) + { + g_critical (G_STRLOC ": Truncating shared memory file failed: %m"); + close (fd); + return NULL; + } + + data = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + + if (data == MAP_FAILED) + { + g_critical (G_STRLOC ": mmap'ping shared memory file failed: %m"); + close (fd); + return NULL; + } + + pool = wl_shm_create_pool (shm, fd, size); + + close (fd); + +-- +2.7.0 + |