[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: Christoph Hellwig <hch@lst.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
e4a53cbabc
commit
e4543eddfd
@ -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)
|
|||||||
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)
|
|||||||
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;
|
||||||
|
23
fs/namei.c
23
fs/namei.c
@ -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)
|
|||||||
|
|
||||||
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)
|
|||||||
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);
|
|||||||
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)
|
|||||||
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
|
||||||
|
12
fs/open.c
12
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))
|
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
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;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user