Commit e4543edd authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Linus Torvalds

[PATCH] add a vfs_permission helper

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: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent e4a53cba
...@@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library) ...@@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library)
if (!S_ISREG(nd.dentry->d_inode->i_mode)) if (!S_ISREG(nd.dentry->d_inode->i_mode))
goto exit; goto exit;
error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); error = vfs_permission(&nd, MAY_READ | MAY_EXEC);
if (error) if (error)
goto exit; goto exit;
...@@ -495,7 +495,7 @@ struct file *open_exec(const char *name) ...@@ -495,7 +495,7 @@ struct file *open_exec(const char *name)
file = ERR_PTR(-EACCES); file = ERR_PTR(-EACCES);
if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && if (!(nd.mnt->mnt_flags & MNT_NOEXEC) &&
S_ISREG(inode->i_mode)) { 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)) if (!err && !(inode->i_mode & 0111))
err = -EACCES; err = -EACCES;
file = ERR_PTR(err); file = ERR_PTR(err);
......
...@@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) ...@@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd)
if (error) if (error)
return error; return error;
/* you can only watch an inode if you have read permissions on it */ /* 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) if (error)
path_release(nd); path_release(nd);
return error; return error;
......
...@@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) ...@@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
return security_inode_permission(inode, mask, 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. * get_write_access() gets write permission for a file.
* put_write_access() releases this write permission. * put_write_access() releases this write permission.
...@@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) ...@@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd)
nd->flags |= LOOKUP_CONTINUE; nd->flags |= LOOKUP_CONTINUE;
err = exec_permission_lite(inode, nd); err = exec_permission_lite(inode, nd);
if (err == -EAGAIN) { if (err == -EAGAIN)
err = permission(inode, MAY_EXEC, nd); err = vfs_permission(nd, MAY_EXEC);
}
if (err) if (err)
break; break;
...@@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) ...@@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE))
return -EISDIR; return -EISDIR;
error = permission(inode, acc_mode, nd); error = vfs_permission(nd, acc_mode);
if (error) if (error)
return error; return error;
...@@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup); ...@@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup);
EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_release);
EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(path_walk);
EXPORT_SYMBOL(permission); EXPORT_SYMBOL(permission);
EXPORT_SYMBOL(vfs_permission);
EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(unlock_rename);
EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_create);
EXPORT_SYMBOL(vfs_follow_link); EXPORT_SYMBOL(vfs_follow_link);
......
...@@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd) ...@@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd)
if (current->uid != nd->dentry->d_inode->i_uid) if (current->uid != nd->dentry->d_inode->i_uid)
return -EPERM; return -EPERM;
} }
if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) if (vfs_permission(nd, MAY_WRITE))
return -EPERM; return -EPERM;
return 0; return 0;
#endif #endif
......
...@@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) ...@@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length)
if (!S_ISREG(inode->i_mode)) if (!S_ISREG(inode->i_mode))
goto dput_and_out; goto dput_and_out;
error = permission(inode,MAY_WRITE,&nd); error = vfs_permission(&nd, MAY_WRITE);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
...@@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) ...@@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
goto dput_and_out; goto dput_and_out;
if (current->fsuid != inode->i_uid && if (current->fsuid != inode->i_uid &&
(error = permission(inode,MAY_WRITE,&nd)) != 0) (error = vfs_permission(&nd, MAY_WRITE)) != 0)
goto dput_and_out; goto dput_and_out;
} }
down(&inode->i_sem); down(&inode->i_sem);
...@@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times) ...@@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times)
goto dput_and_out; goto dput_and_out;
if (current->fsuid != inode->i_uid && if (current->fsuid != inode->i_uid &&
(error = permission(inode,MAY_WRITE,&nd)) != 0) (error = vfs_permission(&nd, MAY_WRITE)) != 0)
goto dput_and_out; goto dput_and_out;
} }
down(&inode->i_sem); down(&inode->i_sem);
...@@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) ...@@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode)
res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
if (!res) { 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 */ /* SuS v2 requires we report a read only fs too */
if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
&& !special_file(nd.dentry->d_inode->i_mode)) && !special_file(nd.dentry->d_inode->i_mode))
...@@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename) ...@@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); error = vfs_permission(&nd, MAY_EXEC);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
...@@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename) ...@@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); error = vfs_permission(&nd, MAY_EXEC);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
......
...@@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb) ...@@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb)
/* /*
* VFS helper functions.. * VFS helper functions..
*/ */
extern int vfs_permission(struct nameidata *, int);
extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *);
extern int vfs_mkdir(struct inode *, struct dentry *, int); extern int vfs_mkdir(struct inode *, struct dentry *, int);
extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t);
......
...@@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, ...@@ -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); err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd);
if (err) if (err)
goto fail; goto fail;
err = permission(nd.dentry->d_inode,MAY_WRITE, &nd); err = vfs_permission(&nd, MAY_WRITE);
if (err) if (err)
goto put_fail; goto put_fail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment