[PATCH 04/46] mm/memfd: make f_pos accesses atomic
Pedro Falcato
pfalcato at suse.de
Tue Oct 27 03:39:25 PDT 2026
On Tue, Oct 27, 2026 at 12:17:24AM +0100, David Hildenbrand (Arm) wrote:
> 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>
Reviewed-by: Pedro Falcato <pfalcato at suse.de>
--
Pedro
More information about the kexec
mailing list