Add a way to check if an fd points to the memfd's original open fd (the one created by memfd_create). Useful because only the original open fd can be both writable and executable.
Signed-off-by: Michal Clapinski mclapinski@google.com --- Documentation/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 +++++++++ 5 files changed, 40 insertions(+)
diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documentation/userspace-api/ioctl/ioctl-number.rst index 4ea5b837399a..9a0782116ac2 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -355,6 +355,7 @@ Code Seq# Include File Comments 0xB6 all linux/fpga-dfl.h 0xB7 all uapi/linux/remoteproc_cdev.h mailto:linux-remoteproc@vger.kernel.org 0xB7 all uapi/linux/nsfs.h <mailto:Andrei Vagin avagin@openvz.org> +0xB8 00 linux/memfd.h 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCA 10-2F uapi/misc/ocxl.h diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 316c4cebd3f3..89ff46f7ac54 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -35,6 +35,7 @@ #include <linux/magic.h> #include <linux/migrate.h> #include <linux/uio.h> +#include <linux/memfd.h>
#include <linux/uaccess.h> #include <linux/sched/mm.h> @@ -1324,6 +1325,12 @@ static void init_once(void *foo) inode_init_once(&ei->vfs_inode); }
+static long hugetlbfs_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return memfd_ioctl(file, cmd, arg); +} + const struct file_operations hugetlbfs_file_operations = { .read_iter = hugetlbfs_read_iter, .mmap = hugetlbfs_file_mmap, @@ -1331,6 +1338,8 @@ const struct file_operations hugetlbfs_file_operations = { .get_unmapped_area = hugetlb_get_unmapped_area, .llseek = default_llseek, .fallocate = hugetlbfs_fallocate, + .unlocked_ioctl = hugetlbfs_file_ioctl, + .compat_ioctl = hugetlbfs_file_ioctl, };
static const struct inode_operations hugetlbfs_dir_inode_operations = { diff --git a/include/linux/memfd.h b/include/linux/memfd.h index e7abf6fa4c52..50f512624c92 100644 --- a/include/linux/memfd.h +++ b/include/linux/memfd.h @@ -3,14 +3,26 @@ #define __LINUX_MEMFD_H
#include <linux/file.h> +#include <linux/ioctl.h>
#ifdef CONFIG_MEMFD_CREATE extern long memfd_fcntl(struct file *file, unsigned int cmd, unsigned int arg); +extern long memfd_ioctl(struct file *file, unsigned int cmd, unsigned int arg); #else static inline long memfd_fcntl(struct file *f, unsigned int c, unsigned int a) { return -EINVAL; } +static inline long memfd_ioctl(struct file *f, unsigned int c, unsigned int a) +{ + return -EINVAL; +} #endif
+/* + * Return 1 if the memfd is original (i.e. was created by memfd_create, + * not reopened), 0 otherwise. + */ +#define MEMFD_CHECK_IF_ORIGINAL _IOR(0xB8, 0, int) + #endif /* __LINUX_MEMFD_H */ diff --git a/mm/memfd.c b/mm/memfd.c index 1cad1904fc26..06bcb970c387 100644 --- a/mm/memfd.c +++ b/mm/memfd.c @@ -262,6 +262,15 @@ long memfd_fcntl(struct file *file, unsigned int cmd, unsigned int arg) return error; }
+long memfd_ioctl(struct file *file, unsigned int cmd, unsigned int arg) +{ + if (cmd == MEMFD_CHECK_IF_ORIGINAL) + return (file->f_mode & FMODE_WRITE) && + !(file->f_mode & FMODE_WRITER); + + return -EINVAL; +} + #define MFD_NAME_PREFIX "memfd:" #define MFD_NAME_PREFIX_LEN (sizeof(MFD_NAME_PREFIX) - 1) #define MFD_NAME_MAX_LEN (NAME_MAX - MFD_NAME_PREFIX_LEN) diff --git a/mm/shmem.c b/mm/shmem.c index 02e62fccc80d..347fcba15fb7 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -79,6 +79,7 @@ static struct vfsmount *shm_mnt; #include <linux/rmap.h> #include <linux/uuid.h> #include <linux/quotaops.h> +#include <linux/memfd.h>
#include <linux/uaccess.h>
@@ -4459,6 +4460,12 @@ const struct address_space_operations shmem_aops = { }; EXPORT_SYMBOL(shmem_aops);
+static long shmem_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return memfd_ioctl(file, cmd, arg); +} + static const struct file_operations shmem_file_operations = { .mmap = shmem_mmap, .open = shmem_file_open, @@ -4471,6 +4478,8 @@ static const struct file_operations shmem_file_operations = { .splice_read = shmem_file_splice_read, .splice_write = iter_file_splice_write, .fallocate = shmem_fallocate, + .unlocked_ioctl = shmem_file_ioctl, + .compat_ioctl = shmem_file_ioctl, #endif };