1
0
Fork 0

[PATCH] fix MAY_CHDIR/MAY_ACCESS/LOOKUP_ACCESS mess

* MAY_CHDIR is redundant - it's an equivalent of MAY_ACCESS
* MAY_ACCESS on fuse should affect only the last step of pathname resolution
* fchdir() and chroot() should pass MAY_ACCESS, for the same reason why
  chdir() needs that.
* now that we pass MAY_ACCESS explicitly in all cases, LOOKUP_ACCESS can be
  removed; it has no business being in nameidata.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
hifive-unleashed-5.1
Al Viro 2008-07-17 09:19:08 -04:00
parent 7f2da1e7d0
commit a110343f0d
5 changed files with 7 additions and 11 deletions

View File

@ -962,7 +962,7 @@ static int fuse_permission(struct inode *inode, int mask)
exist. So if permissions are revoked this won't be exist. So if permissions are revoked this won't be
noticed immediately, only after the attribute noticed immediately, only after the attribute
timeout has expired */ timeout has expired */
} else if (mask & (MAY_ACCESS | MAY_CHDIR)) { } else if (mask & MAY_ACCESS) {
err = fuse_access(inode, mask); err = fuse_access(inode, mask);
} else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) { } else if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) {
if (!(inode->i_mode & S_IXUGO)) { if (!(inode->i_mode & S_IXUGO)) {

View File

@ -265,8 +265,6 @@ int permission(struct inode *inode, int mask, struct nameidata *nd)
if (inode->i_op && inode->i_op->permission) { if (inode->i_op && inode->i_op->permission) {
int extra = 0; int extra = 0;
if (nd) { if (nd) {
if (nd->flags & LOOKUP_ACCESS)
extra |= MAY_ACCESS;
if (nd->flags & LOOKUP_OPEN) if (nd->flags & LOOKUP_OPEN)
extra |= MAY_OPEN; extra |= MAY_OPEN;
} }

View File

@ -457,11 +457,11 @@ asmlinkage long sys_faccessat(int dfd, const char __user *filename, int mode)
old_cap = cap_set_effective(current->cap_permitted); old_cap = cap_set_effective(current->cap_permitted);
} }
res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); res = __user_walk_fd(dfd, filename, LOOKUP_FOLLOW, &nd);
if (res) if (res)
goto out; goto out;
res = vfs_permission(&nd, mode); res = vfs_permission(&nd, mode | MAY_ACCESS);
/* 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) || if(res || !(mode & S_IWOTH) ||
special_file(nd.path.dentry->d_inode->i_mode)) special_file(nd.path.dentry->d_inode->i_mode))
@ -505,7 +505,7 @@ asmlinkage long sys_chdir(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = vfs_permission(&nd, MAY_EXEC | MAY_CHDIR); error = vfs_permission(&nd, MAY_EXEC | MAY_ACCESS);
if (error) if (error)
goto dput_and_out; goto dput_and_out;
@ -534,7 +534,7 @@ asmlinkage long sys_fchdir(unsigned int fd)
if (!S_ISDIR(inode->i_mode)) if (!S_ISDIR(inode->i_mode))
goto out_putf; goto out_putf;
error = file_permission(file, MAY_EXEC); error = file_permission(file, MAY_EXEC | MAY_ACCESS);
if (!error) if (!error)
set_fs_pwd(current->fs, &file->f_path); set_fs_pwd(current->fs, &file->f_path);
out_putf: out_putf:
@ -552,7 +552,7 @@ asmlinkage long sys_chroot(const char __user * filename)
if (error) if (error)
goto out; goto out;
error = vfs_permission(&nd, MAY_EXEC); error = vfs_permission(&nd, MAY_EXEC | MAY_ACCESS);
if (error) if (error)
goto dput_and_out; goto dput_and_out;

View File

@ -61,8 +61,7 @@ extern int dir_notify_enable;
#define MAY_READ 4 #define MAY_READ 4
#define MAY_APPEND 8 #define MAY_APPEND 8
#define MAY_ACCESS 16 #define MAY_ACCESS 16
#define MAY_CHDIR 32 #define MAY_OPEN 32
#define MAY_OPEN 64
#define FMODE_READ 1 #define FMODE_READ 1
#define FMODE_WRITE 2 #define FMODE_WRITE 2

View File

@ -53,7 +53,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
*/ */
#define LOOKUP_OPEN (0x0100) #define LOOKUP_OPEN (0x0100)
#define LOOKUP_CREATE (0x0200) #define LOOKUP_CREATE (0x0200)
#define LOOKUP_ACCESS (0x0400)
extern int __user_walk(const char __user *, unsigned, struct nameidata *); extern int __user_walk(const char __user *, unsigned, struct nameidata *);
extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *); extern int __user_walk_fd(int dfd, const char __user *, unsigned, struct nameidata *);