]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic/memfd: fix memfd_map() seal test 28423/head
authorDavid Rheinsberg <david@readahead.eu>
Mon, 17 Jul 2023 10:17:56 +0000 (12:17 +0200)
committerDavid Rheinsberg <david@readahead.eu>
Tue, 1 Aug 2023 08:14:50 +0000 (10:14 +0200)
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`.

src/basic/memfd-util.c

index a80d586ffa6586bc86497944dded9b228385b7a3..92b84f95a6aff99d41a9fe61c4af8af10bae12f9 100644 (file)
@@ -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);