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))
#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 */
#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;
uint32_t mask;
};
+struct vcmd_ctx_fiattr_v0 {
+ uint32_t xid;
+ uint32_t flags;
+ uint32_t mask;
+};
+
#ifdef __KERNEL__
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 *);
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/parser.h>
+#include <linux/file.h>
#include <linux/compat.h>
#include <linux/vserver/inode.h>
#include <linux/vserver/inode_cmd.h>
#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;
#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;
}
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 */
__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);
__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);