[PATCH 04/46] mm/memfd: make f_pos accesses atomic
David Hildenbrand (Arm)
david at kernel.org
Mon Oct 26 16:17:24 PDT 2026
From: Josef Bacik <josef at toxicpanda.com>
Commit 9c225f2655e3 ("vfs: atomic f_pos accesses as per POSIX") made
read(), write() and lseek() on a shared open file description of a regular
file serialize on ->f_pos_lock. The flag that asks for it,
FMODE_ATOMIC_POS, is set in do_dentry_open(). A memfd is a regular file
too, but its struct file comes from alloc_file_pseudo() and never passes
through do_dentry_open(), so it does not get the flag:
CPU0 CPU1
write(memfd, "a", 1) write(memfd, "b", 1)
pos = file->f_pos (= 0)
pos = file->f_pos (= 0)
vfs_write(..., &pos)
vfs_write(..., &pos)
file->f_pos = pos (= 1)
file->f_pos = pos (= 1)
One of the two bytes is overwritten. Two threads writing 100000 bytes
each, one at a time, to a memfd end up with a file that is far shorter than
200000 bytes, while the same program on a tmpfs file never loses a byte.
Set the flag when the memfd is created. As for any other regular file the
lock is only taken if the file is reachable in more than one way, and
nothing a memfd does in read or write waits for another operation on the
same file. This cannot be done for all alloc_file_pseudo() files: anon
inode files such as eventfd are S_IFREG as well, and a blocked read holding
->f_pos_lock would lock out the write that is supposed to wake it.
Fix generated by an LLM and sent by Josef Bacik in private.
Fixes: 9183df25fe7b ("shm: add memfd_create() syscall")
Cc: stable at vger.kernel.org
Signed-off-by: Josef Bacik <josef at toxicpanda.com>
[ david: minor description tweaks ]
Signed-off-by: David Hildenbrand (Arm) <david at kernel.org>
---
mm/memfd.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/mm/memfd.c b/mm/memfd.c
index 7d2da23157003..6f5fbce74f21e 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -484,6 +484,8 @@ struct file *memfd_alloc_file(const char *name, unsigned int flags)
}
file->f_mode |= FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE;
+ /* a regular file like any other: POSIX.1-2008/SUSv4 Section XSI 2.9.7 */
+ file->f_mode |= FMODE_ATOMIC_POS;
file->f_flags |= O_LARGEFILE;
if (flags & MFD_NOEXEC_SEAL) {
--
2.43.0
More information about the kexec
mailing list