From 03e304544b9b01c175813215f5930a07152be448 Mon Sep 17 00:00:00 2001 From: 6t8k <6t8k@noreply.codeberg.org> Date: Sat, 14 Oct 2023 23:25:48 +0200 Subject: [PATCH] cursor: memfd_create: try MFD_NOEXEC_SEAL Effective from Linux 6.3 onward, this creates the memfd without execute permissions and prevents that setting from ever being changed. A run-time fallback is made to not using MFD_NOEXEC_SEAL when a libwayland-cursor compiled on Linux >= 6.3 is run on Linux < 6.3. This is a defense-in-depth security measure and silences a respective kernel warning; see: https://lwn.net/Articles/918106/ This implementation is adopted from dnkl's `foot` terminal emulator. Signed-off-by: 6t8k <6t8k@noreply.codeberg.org> --- cursor/os-compatibility.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/cursor/os-compatibility.c b/cursor/os-compatibility.c index f2445ced..2b54bae2 100644 --- a/cursor/os-compatibility.c +++ b/cursor/os-compatibility.c @@ -40,6 +40,11 @@ #include #endif +/* Fallback to no flag when missing the definition */ +#ifndef MFD_NOEXEC_SEAL +#define MFD_NOEXEC_SEAL 0 +#endif + #include "os-compatibility.h" #ifndef HAVE_MKOSTEMP @@ -124,7 +129,21 @@ os_create_anonymous_file(off_t size) int fd; #ifdef HAVE_MEMFD_CREATE - fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING); + /* + * Linux kernels older than 6.3 reject MFD_NOEXEC_SEAL with EINVAL. + * Try first *with* it, and if that fails, try again *without* it. + */ + errno = 0; + fd = memfd_create( + "wayland-cursor", + MFD_CLOEXEC | MFD_ALLOW_SEALING | MFD_NOEXEC_SEAL); + + if (fd < 0 && errno == EINVAL && MFD_NOEXEC_SEAL != 0) { + fd = memfd_create( + "wayland-cursor", + MFD_CLOEXEC | MFD_ALLOW_SEALING); + } + if (fd >= 0) { /* We can add this seal before calling posix_fallocate(), as * the file is currently zero-sized anyway.