diff --git a/fs/epfs/epfs.h b/fs/epfs/epfs.h index 1b6f1087cf04b3f4b3f670a482343cc0f90ff88d..19e66e145d1ab14df2660a5f5738c587b0f20503 100644 --- a/fs/epfs/epfs.h +++ b/fs/epfs/epfs.h @@ -27,6 +27,7 @@ struct __attribute__((__packed__)) epfs_range { #define EPFS_IOCTL_MAGIC 0x71 #define IOC_SET_ORIGIN_FD _IOW(EPFS_IOCTL_MAGIC, 1, __s32) #define IOC_SET_EPFS_RANGE _IOW(EPFS_IOCTL_MAGIC, 2, struct epfs_range) +#define EPFS_IOCTL_MAXNR 3 #define EPFS_TAG "Epfs" diff --git a/fs/epfs/file.c b/fs/epfs/file.c index adb45177a267eb9433051cab37e8691ca0b34082..5b236150f8b40ed129fcaf9123825f9b80b4fe0c 100644 --- a/fs/epfs/file.c +++ b/fs/epfs/file.c @@ -86,6 +86,7 @@ int check_range(struct epfs_range *range) long epfs_set_range(struct file *file, unsigned long arg) { struct inode *inode = file->f_inode; + struct inode *origin_inode; struct epfs_inode_info *info = epfs_inode_to_private(inode); int ret = 0; struct epfs_range *range; @@ -97,6 +98,13 @@ long epfs_set_range(struct file *file, unsigned long arg) ret = -EBADF; goto out_set_range; } + origin_inode = info->origin_file->f_inode; + if (!in_group_p(origin_inode->i_gid)) { + epfs_err("Only group member can set range: %u", + i_gid_read(origin_inode)); + ret = -EACCES; + goto out_set_range; + } if (copy_from_user(&header, (struct epfs_range *)arg, sizeof(header))) { @@ -143,6 +151,19 @@ static long __epfs_ioctl(struct file *file, unsigned int cmd, { long rc = -ENOTTY; + if (unlikely(_IOC_TYPE(cmd) != EPFS_IOCTL_MAGIC)) { + epfs_err("Failed to check epfs magic: %u", _IOC_TYPE(cmd)); + return -ENOTTY; + } + if (unlikely(_IOC_NR(cmd) >= EPFS_IOCTL_MAXNR)) { + epfs_err("Failed to check ioctl number: %u", _IOC_NR(cmd)); + return -ENOTTY; + } + if (unlikely(!access_ok((void __user *)arg, _IOC_SIZE(cmd)))) { + epfs_err("Failed to check user address space range!"); + return -EFAULT; + } + switch (cmd) { case IOC_SET_ORIGIN_FD: return epfs_set_origin_fd(file, arg);