Wayland: Use memfd_create() and seals if available

This allows the compositor to avoid having to setup and teardown a
SIGBUS signal handler whenever it needs to read from this surface, as it
knows we won’t be able to shrink the file and so doesn’t have to protect
against that.

Only enabled on Linux, since only Linux has memfd_create()
This commit is contained in:
Kovid Goyal 2018-10-03 09:47:04 +05:30
parent 21f6c6a5a8
commit ac98b85157
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 64 additions and 13 deletions

51
glfw/memfd.h vendored Normal file
View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2018 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#pragma once
#if defined(__linux__)
#define _GNU_SOURCE
#include <unistd.h>
#include <sys/syscall.h>
static inline int memfd_create(const char *name, unsigned int flags) {
return syscall(__NR_memfd_create, name, flags);
}
#ifndef F_LINUX_SPECIFIC_BASE
#define F_LINUX_SPECIFIC_BASE 1024
#endif
#ifndef F_ADD_SEALS
#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
#define F_SEAL_GROW 0x0004 /* prevent file from growing */
#define F_SEAL_WRITE 0x0008 /* prevent writes */
#endif
#ifndef MFD_CLOEXEC
#define MFD_CLOEXEC 0x0001U
#define MFD_ALLOW_SEALING 0x0002U
#endif
#else
static inline int
createTmpfileCloexec(char* tmpname)
{
int fd;
fd = mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0)
unlink(tmpname);
return fd;
}
#endif

26
glfw/wl_window.c vendored
View File

@ -28,6 +28,7 @@
#include "internal.h" #include "internal.h"
#include "backend_utils.h" #include "backend_utils.h"
#include "memfd.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -115,18 +116,6 @@ static const struct wl_shell_surface_listener shellSurfaceListener = {
handlePopupDone handlePopupDone
}; };
static int
createTmpfileCloexec(char* tmpname)
{
int fd;
fd = mkostemp(tmpname, O_CLOEXEC);
if (fd >= 0)
unlink(tmpname);
return fd;
}
/* /*
* Create a new, unique, anonymous file of the given size, and * Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set * return the file descriptor for it. The file descriptor is set
@ -150,11 +139,21 @@ createTmpfileCloexec(char* tmpname)
static int static int
createAnonymousFile(off_t size) createAnonymousFile(off_t size)
{ {
int ret;
#if defined(__linux__)
int fd = memfd_create("glfw-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd < 0) return -1;
// We can add this seal before calling posix_fallocate(), as the file
// is currently zero-sized anyway.
//
// There is also no need to check for the return value, we couldnt do
// anything with it anyway.
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
#else
static const char template[] = "/glfw-shared-XXXXXX"; static const char template[] = "/glfw-shared-XXXXXX";
const char* path; const char* path;
char* name; char* name;
int fd; int fd;
int ret;
path = getenv("XDG_RUNTIME_DIR"); path = getenv("XDG_RUNTIME_DIR");
if (!path) if (!path)
@ -173,6 +172,7 @@ createAnonymousFile(off_t size)
if (fd < 0) if (fd < 0)
return -1; return -1;
#endif
ret = posix_fallocate(fd, 0, size); ret = posix_fallocate(fd, 0, size);
if (ret != 0) if (ret != 0)
{ {