From 6ac40fa45170084f36e0c719373da41dd9a6c3c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barnab=C3=A1s=20P=C5=91cze?= Date: Thu, 23 May 2024 03:15:06 +0200 Subject: [PATCH] util/misc: support kernels where `MFD_NOEXEC_SEAL` does not enable sealing Newer Linux kernels do not unset `F_SEAL_SEAL` when `MFD_NOEXEC_SEAL` is supplied to `memfd_create()`[0]. Currently, `misc_memfd()` has a workaround for this peculiarity of the kernel, however, this workaround will break. Avoid the breakage by checking if the kernel added `F_SEAL_SEAL`, and only try to add it if it is not already present. Note that this kernel uAPI change does not affect dbus-broker's normal operations since it never attempts to create a memfd with `MFD_NOEXEC_SEAL` and without `MFD_ALLOW_SEALING`. Only the test suite would be broken on newer kernels without this change. [0]: https://lore.kernel.org/linux-mm/20240524033933.135049-1-jeffxu@google.com/ --- src/util/misc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/util/misc.c b/src/util/misc.c index a505caf7..99613440 100644 --- a/src/util/misc.c +++ b/src/util/misc.c @@ -49,7 +49,7 @@ * Throw in `MFD_CLOEXEC` or `F_SEAL_SEAL` as required. * * * If `MFD_NOEXEC_SEAL` is used without `MFD_ALLOW_SEALING`, sealing will - * be disabled (even though the kernel implicitly enables it). + * be disabled (even though some kernel versions implicitly enable it). * * * An initial set of seals is applied to the memfd, if specified in * @seals. Note that this is not allowed if sealing was not enabled. @@ -111,7 +111,7 @@ int misc_memfd(const char *name, unsigned int uflags, unsigned int useals) { } /* - * If we ended up passing `MFG_NOEXEC_SEAL` to the kernel, the kernel + * If we ended up passing `MFG_NOEXEC_SEAL` to the kernel, some kernel versions * will implicitly enable sealing. This is very unfortunate, so we * revert this if the caller did not explicitly allow it. To disable * sealing, simply set `F_SEAL_SEAL`, which is also what the kernel @@ -126,9 +126,15 @@ int misc_memfd(const char *name, unsigned int uflags, unsigned int useals) { * into the kernel again. */ if (seals) { - r = misc_memfd_add_seals(fd, seals); - if (r) - return error_fold(r); + r = fcntl(fd, MISC_F_GET_SEALS); + if (r < 0) + return error_origin(-errno); + + if (seals & ~r) { + r = misc_memfd_add_seals(fd, seals); + if (r) + return error_fold(r); + } } r = fd;