diff options
author | David Rheinsberg <david@readahead.eu> | 2023-07-17 12:17:56 +0200 |
---|---|---|
committer | David Rheinsberg <david@readahead.eu> | 2023-08-01 10:14:50 +0200 |
commit | 69688410566aa9e2a00530abd91e7dfef0212c83 (patch) | |
tree | cd1d8fec394befb433e326a07ac248969a5a7086 | |
parent | basic/memfd: add fcntl() wrappers (diff) | |
download | systemd-69688410566aa9e2a00530abd91e7dfef0212c83.tar.xz systemd-69688410566aa9e2a00530abd91e7dfef0212c83.zip |
basic/memfd: fix memfd_map() seal test
Private mappings are required when F_SEAL_WRITE is set on a memfd,
because otherwise you could end up with writable mappings through
mprotect() and other calls. This is a limitation of the kernel
implementation, and might be lifted by future extensions.
Regardless, the current code tests for the full `is_sealed()` before
using MAP_PRIVATE. This might end up using MAP_SHARED for write-sealed
memfds, which will be refused by the kernel.
Fix this and make memfd_map() check for exactly `F_SEAL_WRITE`.
-rw-r--r-- | src/basic/memfd-util.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/src/basic/memfd-util.c b/src/basic/memfd-util.c index a80d586ffa..92b84f95a6 100644 --- a/src/basic/memfd-util.c +++ b/src/basic/memfd-util.c @@ -89,18 +89,19 @@ int memfd_get_seals(int fd, unsigned int *ret_seals) { } int memfd_map(int fd, uint64_t offset, size_t size, void **p) { + unsigned int seals; void *q; - int sealed; + int r; assert(fd >= 0); assert(size > 0); assert(p); - sealed = memfd_get_sealed(fd); - if (sealed < 0) - return sealed; + r = memfd_get_seals(fd, &seals); + if (r < 0) + return r; - if (sealed) + if (seals & F_SEAL_WRITE) q = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, offset); else q = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset); |