This change introduces a way to check if an fd points to a memfd's original open fd (the one created by memfd_create).
We encountered an issue with migrating memfds in CRIU (checkpoint restore in userspace - it migrates running processes between machines). Imagine a scenario: 1. Create a memfd. By default it's open with O_RDWR and yet one can exec() to it (unlike with regular files, where one would get ETXTBSY). 2. Reopen that memfd with O_RDWR via /proc/self/fd/<fd>.
Now those 2 fds are indistinguishable from userspace. You can't exec() to either of them (since the reopen incremented inode->i_writecount) and their /proc/self/fdinfo/ are exactly the same. Unfortunately they are not the same. If you close the second one, the first one becomes exec()able again. If you close the first one, the other doesn't become exec()able. Therefore during migration it does matter which is recreated first and which is reopened but there is no way for CRIU to tell which was first.
--- Changes since v1 at [1]: - Rewrote it from fcntl to ioctl. This was requested by filesystems maintainer.
Links: [1] https://lore.kernel.org/all/20230831203647.558079-1-mclapinski@google.com/
Michal Clapinski (2): mm/memfd: add ioctl(MEMFD_CHECK_IF_ORIGINAL) selftests: test ioctl(MEMFD_CHECK_IF_ORIGINAL)
.../userspace-api/ioctl/ioctl-number.rst | 1 + fs/hugetlbfs/inode.c | 9 ++++++ include/linux/memfd.h | 12 +++++++ mm/memfd.c | 9 ++++++ mm/shmem.c | 9 ++++++ tools/testing/selftests/memfd/memfd_test.c | 32 +++++++++++++++++++ 6 files changed, 72 insertions(+)