summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorChris Mason <mason@kernel.org>2026-10-29 11:43:25 +0100
committerDavid Hildenbrand (Arm) <david@kernel.org>2026-11-02 11:21:28 +0100
commit0237c47ca17005ea41b510c6116f0257dbf84eab (patch)
tree6c951fd3362eb2322e0456e094aba921910c0570 /include
parentd5d861ee303da01e59fdf8e8b2f7096c76e7efd5 (diff)
mm/shmem: honour F_SEAL_EXEC when an ACL is set
The owner of a memfd sealed with F_SEAL_EXEC can still change its execute bits by setting a POSIX access ACL. With CONFIG_TMPFS_POSIX_ACL, this lets an unprivileged owner make a non-executable memfd executable, bypassing vm.memfd_noexec=2. simple_set_acl() updates i_mode directly, bypassing the seal check in shmem_setattr(). Add shmem_set_acl() to check the resulting mode. Share the F_SEAL_EXEC check with shmem_setattr() using memfd_check_seals_mode() in include/linux/memfd.h. Fix generated by an LLM and sent by Chris Mason in private. Fixes: 6fd7353829ca ("mm/memfd: add F_SEAL_EXEC") Cc: stable@vger.kernel.org Signed-off-by: Chris Mason <mason@kernel.org> Acked-by: Pedro Falcato <pfalcato@suse.de> Acked-by: Kiryl Shutsemau (Meta) <kas@kernel.org> Acked-by: Zi Yan <ziy@nvidia.com> Reviewed-by: Baolin Wang <baolin.wang@linux.alibaba.com> Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org> Tested-by: Gregory Price (Meta) <gourry@gourry.net> [ david: use common helper; simplify description ] Link: https://patch.msgid.link/20261029-fixes_shmem-v4-4-392fc715d8f6@kernel.org Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/memfd.h9
1 files changed, 9 insertions, 0 deletions
diff --git a/include/linux/memfd.h b/include/linux/memfd.h
index c159e40e3f34..272479317cf1 100644
--- a/include/linux/memfd.h
+++ b/include/linux/memfd.h
@@ -2,10 +2,19 @@
#ifndef __LINUX_MEMFD_H
#define __LINUX_MEMFD_H
+#include <linux/fcntl.h>
#include <linux/file.h>
#define MEMFD_ANON_NAME "[memfd]"
+static inline int memfd_check_seals_mode(unsigned int seals, umode_t old_mode,
+ umode_t new_mode)
+{
+ if ((seals & F_SEAL_EXEC) && ((old_mode ^ new_mode) & 0111))
+ return -EPERM;
+ return 0;
+}
+
#ifdef CONFIG_MEMFD_CREATE
extern long memfd_fcntl(struct file *file, unsigned int cmd, unsigned int arg);
struct folio *memfd_alloc_folio(struct file *memfd, pgoff_t idx);