From 7ad071ec7adac653c87d31b9febf0d3d434c572d Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Thu, 12 Jul 2007 18:13:44 +0000 Subject: [PATCH] get rid of ioctls, use vserver syscall interface --- fs/ioctl.c | 15 ------- include/linux/vserver/inode.h | 3 -- include/linux/vserver/inode_cmd.h | 12 ++++++ kernel/vserver/inode.c | 68 +++++++++++++++++++------------ kernel/vserver/switch.c | 7 ++++ 5 files changed, 62 insertions(+), 43 deletions(-) diff --git a/fs/ioctl.c b/fs/ioctl.c index b1c6cab06..992cdb7c2 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -197,21 +197,6 @@ int vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, unsigned lon error = vx_proc_ioctl(filp->f_dentry->d_inode, filp, cmd, arg); break; #endif - /* - * These cmds needed for PLK - don't lose them! - */ - case FIOC_SETIATTR: - case FIOC_GETIATTR: - /* - * Verify that this filp is a file object, - * not (say) a socket. - */ - error = -ENOTTY; - if (S_ISREG(filp->f_dentry->d_inode->i_mode) || - S_ISDIR(filp->f_dentry->d_inode->i_mode)) - error = vc_iattr_ioctl(filp->f_dentry, - cmd, arg); - break; default: if (S_ISREG(filp->f_path.dentry->d_inode->i_mode)) diff --git a/include/linux/vserver/inode.h b/include/linux/vserver/inode.h index 2b354768b..333e2f532 100644 --- a/include/linux/vserver/inode.h +++ b/include/linux/vserver/inode.h @@ -37,9 +37,6 @@ extern int vc_iattr_ioctl(struct dentry *de, #define FIOC_GETXFLG _IOR('x', 5, long) #define FIOC_SETXFLG _IOW('x', 6, long) -#define FIOC_GETIATTR _IOR('x', 7, long) -#define FIOC_SETIATTR _IOR('x', 8, long) - #else /* _VX_INODE_H */ #warning duplicate inclusion #endif /* _VX_INODE_H */ diff --git a/include/linux/vserver/inode_cmd.h b/include/linux/vserver/inode_cmd.h index 2fb3ad16c..1a6d826cb 100644 --- a/include/linux/vserver/inode_cmd.h +++ b/include/linux/vserver/inode_cmd.h @@ -10,6 +10,9 @@ #define VCMD_get_iattr VC_CMD(INODE, 1, 1) #define VCMD_set_iattr VC_CMD(INODE, 2, 1) +#define VCMD_fget_iattr VC_CMD(INODE, 3, 0) +#define VCMD_fset_iattr VC_CMD(INODE, 4, 0) + struct vcmd_ctx_iattr_v0 { /* device handle in id */ uint64_t ino; @@ -25,6 +28,12 @@ struct vcmd_ctx_iattr_v1 { uint32_t mask; }; +struct vcmd_ctx_fiattr_v0 { + uint32_t xid; + uint32_t flags; + uint32_t mask; +}; + #ifdef __KERNEL__ @@ -50,6 +59,9 @@ extern int vc_set_iattr_v0(uint32_t, void __user *); extern int vc_get_iattr(uint32_t, void __user *); extern int vc_set_iattr(uint32_t, void __user *); +extern int vc_fget_iattr(uint32_t, void __user *); +extern int vc_fset_iattr(uint32_t, void __user *); + #ifdef CONFIG_COMPAT extern int vc_get_iattr_x32(uint32_t, void __user *); diff --git a/kernel/vserver/inode.c b/kernel/vserver/inode.c index 2cffdf114..23a59a83d 100644 --- a/kernel/vserver/inode.c +++ b/kernel/vserver/inode.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -123,6 +124,30 @@ int vc_get_iattr_x32(uint32_t id, void __user *data) #endif /* CONFIG_COMPAT */ +int vc_fget_iattr(uint32_t fd, void __user *data) +{ + struct file *filp; + struct vcmd_ctx_fiattr_v0 vc_data = { .xid = -1 }; + int ret; + + if (copy_from_user (&vc_data, data, sizeof(vc_data))) + return -EFAULT; + + filp = fget(fd); + if (!filp || !filp->f_dentry || !filp->f_dentry->d_inode) + return -EBADF; + + ret = __vc_get_iattr(filp->f_dentry->d_inode, + &vc_data.xid, &vc_data.flags, &vc_data.mask); + + fput(filp); + + if (copy_to_user (data, &vc_data, sizeof(vc_data))) + ret = -EFAULT; + return ret; +} + + static int __vc_set_iattr(struct dentry *de, uint32_t *tag, uint32_t *flags, uint32_t *mask) { struct inode *in = de->d_inode; @@ -249,35 +274,28 @@ int vc_set_iattr_x32(uint32_t id, void __user *data) #endif /* CONFIG_COMPAT */ -/* required by PLK */ -int vc_iattr_ioctl(struct dentry *de, unsigned int cmd, unsigned long arg) +int vc_fset_iattr(uint32_t fd, void __user *data) { - void __user *data = (void __user *)arg; - struct vcmd_ctx_iattr_v1 vc_data; + struct file *filp; + struct vcmd_ctx_fiattr_v0 vc_data; int ret; - /* - * I don't think we need any dget/dput pairs in here as long as - * this function is always called from sys_ioctl i.e., de is - * a field of a struct file that is guaranteed not to be freed. - */ - if (cmd == FIOC_SETIATTR) { - if (!capable(CAP_SYS_ADMIN) || !capable(CAP_LINUX_IMMUTABLE)) - return -EPERM; - if (copy_from_user (&vc_data, data, sizeof(vc_data))) - return -EFAULT; - ret = __vc_set_iattr(de, - &vc_data.xid, &vc_data.flags, &vc_data.mask); - } - else { - if (!vx_check(0, VS_ADMIN)) - return -ENOSYS; - ret = __vc_get_iattr(de->d_inode, - &vc_data.xid, &vc_data.flags, &vc_data.mask); - } + if (!capable(CAP_LINUX_IMMUTABLE)) + return -EPERM; + if (copy_from_user(&vc_data, data, sizeof(vc_data))) + return -EFAULT; - if (!ret && copy_to_user (data, &vc_data, sizeof(vc_data))) - ret = -EFAULT; + filp = fget(fd); + if (!filp || !filp->f_dentry || !filp->f_dentry->d_inode) + return -EBADF; + + ret = __vc_set_iattr(filp->f_dentry, &vc_data.xid, + &vc_data.flags, &vc_data.mask); + + fput(filp); + + if (copy_to_user(data, &vc_data, sizeof(vc_data))) + return -EFAULT; return ret; } diff --git a/kernel/vserver/switch.c b/kernel/vserver/switch.c index 67b387009..36e8968c9 100644 --- a/kernel/vserver/switch.c +++ b/kernel/vserver/switch.c @@ -200,6 +200,11 @@ long do_vcmd(uint32_t cmd, uint32_t id, case VCMD_set_iattr: return __COMPAT(vc_set_iattr, id, data, compat); + case VCMD_fget_iattr: + return vc_fget_iattr(id, data); + case VCMD_fset_iattr: + return vc_fset_iattr(id, data); + case VCMD_enter_space_v0: return vc_enter_space(vxi, NULL); /* this is version 1 */ @@ -308,6 +313,7 @@ long do_vserver(uint32_t cmd, uint32_t id, void __user *data, int compat) __VCMD(get_nflags, 3, VCA_NXI, VCF_INFO); __VCMD(get_iattr, 2, VCA_NONE, 0); + __VCMD(fget_iattr, 2, VCA_NONE, 0); __VCMD(get_dlimit, 3, VCA_NONE, VCF_INFO); __VCMD(get_sched, 3, VCA_VXI, VCF_INFO); __VCMD(sched_info, 3, VCA_VXI, VCF_INFO|VCF_ZIDOK); @@ -348,6 +354,7 @@ long do_vserver(uint32_t cmd, uint32_t id, void __user *data, int compat) __VCMD(net_remove, 8, VCA_NXI, VCF_ARES|VCF_SETUP); __VCMD(set_iattr, 7, VCA_NONE, 0); + __VCMD(fset_iattr, 7, VCA_NONE, 0); __VCMD(set_dlimit, 7, VCA_NONE, VCF_ARES); __VCMD(add_dlimit, 8, VCA_NONE, VCF_ARES); __VCMD(rem_dlimit, 8, VCA_NONE, VCF_ARES); -- 2.47.0