Need a way to manipulate vserver file attrs using a file descriptor
authorSteve Muir <smuir@cs.princeton.edu>
Thu, 18 Nov 2004 20:06:31 +0000 (20:06 +0000)
committerSteve Muir <smuir@cs.princeton.edu>
Thu, 18 Nov 2004 20:06:31 +0000 (20:06 +0000)
fs/ioctl.c
include/linux/vserver/inode.h
kernel/vserver/inode.c

index 96a1b60..6404b0c 100644 (file)
@@ -173,6 +173,19 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
                                error = vx_proc_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
                        break;
 #endif
+               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:
                        error = -ENOTTY;
                        if (S_ISREG(filp->f_dentry->d_inode->i_mode))
index aa8852f..e19632d 100644 (file)
@@ -39,7 +39,7 @@ struct  vcmd_ctx_iattr_v1 {
 #define IATTR_IMMUTABLE        0x00040000
 
 
-#ifdef CONFIG_PROC_SECURE
+#ifdef CONFIG_VSERVER_PROC_SECURE
 #define IATTR_PROC_DEFAULT     ( IATTR_ADMIN | IATTR_HIDE )
 #define IATTR_PROC_SYMLINK     ( IATTR_ADMIN )
 #else
@@ -57,6 +57,10 @@ 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_iattr_ioctl(struct dentry *de,
+                         unsigned int cmd,
+                         unsigned long arg);
+
 #endif /* __KERNEL__ */
 
 /* inode ioctls */
@@ -64,4 +68,7 @@ extern int vc_set_iattr(uint32_t, void __user *);
 #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)
+
 #endif /* _VX_INODE_H */
index 87e2849..d28749b 100644 (file)
@@ -10,7 +10,8 @@
  */
 
 #include <linux/config.h>
-#include <linux/vinline.h>
+#include <linux/vs_base.h>
+#include <linux/vs_context.h>
 #include <linux/fs.h>
 #include <linux/proc_fs.h>
 #include <linux/namei.h>
@@ -169,6 +170,37 @@ int vc_set_iattr(uint32_t id, void __user *data)
        return ret;
 }
 
+int vc_iattr_ioctl(struct dentry *de, unsigned int cmd, unsigned long arg)
+{
+       void __user *data = (void __user *)arg;
+       struct vcmd_ctx_iattr_v1 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., the big
+        * kernel lock is held.
+        */
+       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, VX_ADMIN))
+                       return -ENOSYS;
+               ret = __vc_get_iattr(de->d_inode,
+                       &vc_data.xid, &vc_data.flags, &vc_data.mask);
+       }
+
+       if (!ret && copy_to_user (data, &vc_data, sizeof(vc_data)))
+               ret = -EFAULT;
+       return ret;
+}
+
 
 #ifdef CONFIG_VSERVER_LEGACY           
 #include <linux/proc_fs.h>