[PATCH] add a vfs_permission helper
Christoph Hellwig [Wed, 9 Nov 2005 05:35:04 +0000 (21:35 -0800)]
Most permission() calls have a struct nameidata * available.  This helper
takes that as an argument and thus makes sure we pass it down for lookup
intents and prepares for per-mount read-only support where we need a struct
vfsmount for checking whether a file is writeable.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

fs/exec.c
fs/inotify.c
fs/namei.c
fs/namespace.c
fs/open.c
include/linux/fs.h
net/unix/af_unix.c

index 5a4e3ac..7bbb781 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library)
        if (!S_ISREG(nd.dentry->d_inode->i_mode))
                goto exit;
 
-       error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd);
+       error = vfs_permission(&nd, MAY_READ | MAY_EXEC);
        if (error)
                goto exit;
 
@@ -495,7 +495,7 @@ struct file *open_exec(const char *name)
                file = ERR_PTR(-EACCES);
                if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
                    S_ISREG(inode->i_mode)) {
-                       int err = permission(inode, MAY_EXEC, &nd);
+                       int err = vfs_permission(&nd, MAY_EXEC);
                        if (!err && !(inode->i_mode & 0111))
                                err = -EACCES;
                        file = ERR_PTR(err);
index 9fbaebf..bf7ce1d 100644 (file)
@@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd)
        if (error)
                return error;
        /* you can only watch an inode if you have read permissions on it */
-       error = permission(nd->dentry->d_inode, MAY_READ, NULL);
+       error = vfs_permission(nd, MAY_READ);
        if (error) 
                path_release(nd);
        return error;
index b3f8a19..25e4ab4 100644 (file)
@@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
        return security_inode_permission(inode, mask, nd);
 }
 
+/**
+ * vfs_permission  -  check for access rights to a given path
+ * @nd:                lookup result that describes the path
+ * @mask:      right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Used to check for read/write/execute permissions on a path.
+ * We use "fsuid" for this, letting us set arbitrary permissions
+ * for filesystem access without changing the "normal" uids which
+ * are used for other things.
+ */
+int vfs_permission(struct nameidata *nd, int mask)
+{
+       return permission(nd->dentry->d_inode, mask, nd);
+}
+
 /*
  * get_write_access() gets write permission for a file.
  * put_write_access() releases this write permission.
@@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
 
                nd->flags |= LOOKUP_CONTINUE;
                err = exec_permission_lite(inode, nd);
-               if (err == -EAGAIN) { 
-                       err = permission(inode, MAY_EXEC, nd);
-               }
+               if (err == -EAGAIN)
+                       err = vfs_permission(nd, MAY_EXEC);
                if (err)
                        break;
 
@@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
        if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
                return -EISDIR;
 
-       error = permission(inode, acc_mode, nd);
+       error = vfs_permission(nd, acc_mode);
        if (error)
                return error;
 
@@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup);
 EXPORT_SYMBOL(path_release);
 EXPORT_SYMBOL(path_walk);
 EXPORT_SYMBOL(permission);
+EXPORT_SYMBOL(vfs_permission);
 EXPORT_SYMBOL(unlock_rename);
 EXPORT_SYMBOL(vfs_create);
 EXPORT_SYMBOL(vfs_follow_link);
index caa9187..2019899 100644 (file)
@@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd)
                if (current->uid != nd->dentry->d_inode->i_uid)
                        return -EPERM;
        }
-       if (permission(nd->dentry->d_inode, MAY_WRITE, nd))
+       if (vfs_permission(nd, MAY_WRITE))
                return -EPERM;
        return 0;
 #endif
index 6e81367..baffc08 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
        if (!S_ISREG(inode->i_mode))
                goto dput_and_out;
 
-       error = permission(inode,MAY_WRITE,&nd);
+       error = vfs_permission(&nd, MAY_WRITE);
        if (error)
                goto dput_and_out;
 
@@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
                         goto dput_and_out;
 
                if (current->fsuid != inode->i_uid &&
-                   (error = permission(inode,MAY_WRITE,&nd)) != 0)
+                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
                        goto dput_and_out;
        }
        down(&inode->i_sem);
@@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times)
                         goto dput_and_out;
 
                if (current->fsuid != inode->i_uid &&
-                   (error = permission(inode,MAY_WRITE,&nd)) != 0)
+                   (error = vfs_permission(&nd, MAY_WRITE)) != 0)
                        goto dput_and_out;
        }
        down(&inode->i_sem);
@@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode)
 
        res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
        if (!res) {
-               res = permission(nd.dentry->d_inode, mode, &nd);
+               res = vfs_permission(&nd, mode);
                /* SuS v2 requires we report a read only fs too */
                if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
                   && !special_file(nd.dentry->d_inode->i_mode))
@@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename)
        if (error)
                goto out;
 
-       error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
+       error = vfs_permission(&nd, MAY_EXEC);
        if (error)
                goto dput_and_out;
 
@@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename)
        if (error)
                goto out;
 
-       error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
+       error = vfs_permission(&nd, MAY_EXEC);
        if (error)
                goto dput_and_out;
 
index 1b5f502..c3b8c1d 100644 (file)
@@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb)
 /*
  * VFS helper functions..
  */
+extern int vfs_permission(struct nameidata *, int);
 extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
 extern int vfs_mkdir(struct inode *, struct dentry *, int);
 extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
index 41feca3..acc73ba 100644 (file)
@@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len,
                err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
                if (err)
                        goto fail;
-               err = permission(nd.dentry->d_inode,MAY_WRITE, &nd);
+               err = vfs_permission(&nd, MAY_WRITE);
                if (err)
                        goto put_fail;