don't carry MAY_OPEN in op->acc_mode
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 27 Dec 2015 03:33:24 +0000 (22:33 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 4 Jan 2016 15:28:40 +0000 (10:28 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/exec.c
fs/namei.c
fs/open.c

index b06623a..828ec5f 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -119,7 +119,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
        int error = PTR_ERR(tmp);
        static const struct open_flags uselib_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
-               .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
+               .acc_mode = MAY_READ | MAY_EXEC,
                .intent = LOOKUP_OPEN,
                .lookup_flags = LOOKUP_FOLLOW,
        };
@@ -763,7 +763,7 @@ static struct file *do_open_execat(int fd, struct filename *name, int flags)
        int err;
        struct open_flags open_exec_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
-               .acc_mode = MAY_EXEC | MAY_OPEN,
+               .acc_mode = MAY_EXEC,
                .intent = LOOKUP_OPEN,
                .lookup_flags = LOOKUP_FOLLOW,
        };
index 9e102ac..45c702e 100644 (file)
@@ -2663,10 +2663,6 @@ static int may_open(struct path *path, int acc_mode, int flag)
        struct inode *inode = dentry->d_inode;
        int error;
 
-       /* O_PATH? */
-       if (!acc_mode)
-               return 0;
-
        if (!inode)
                return -ENOENT;
 
@@ -2688,7 +2684,7 @@ static int may_open(struct path *path, int acc_mode, int flag)
                break;
        }
 
-       error = inode_permission(inode, acc_mode);
+       error = inode_permission(inode, MAY_OPEN | acc_mode);
        if (error)
                return error;
 
@@ -2880,7 +2876,7 @@ static int atomic_open(struct nameidata *nd, struct dentry *dentry,
        if (*opened & FILE_CREATED) {
                WARN_ON(!(open_flag & O_CREAT));
                fsnotify_create(dir, dentry);
-               acc_mode = MAY_OPEN;
+               acc_mode = 0;
        }
        error = may_open(&file->f_path, acc_mode, open_flag);
        if (error)
@@ -3093,7 +3089,7 @@ retry_lookup:
                /* Don't check for write permission, don't truncate */
                open_flag &= ~O_TRUNC;
                will_truncate = false;
-               acc_mode = MAY_OPEN;
+               acc_mode = 0;
                path_to_nameidata(&path, nd);
                goto finish_open_created;
        }
@@ -3177,10 +3173,11 @@ finish_open:
                got_write = true;
        }
 finish_open_created:
-       error = may_open(&nd->path, acc_mode, open_flag);
-       if (error)
-               goto out;
-
+       if (likely(!(open_flag & O_PATH))) {
+               error = may_open(&nd->path, acc_mode, open_flag);
+               if (error)
+                       goto out;
+       }
        BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
        error = vfs_open(&nd->path, file, current_cred());
        if (!error) {
@@ -3267,7 +3264,7 @@ static int do_tmpfile(struct nameidata *nd, unsigned flags,
                goto out2;
        audit_inode(nd->name, child, 0);
        /* Don't check for other permissions, the inode was just created */
-       error = may_open(&path, MAY_OPEN, op->open_flag);
+       error = may_open(&path, 0, op->open_flag);
        if (error)
                goto out2;
        file->f_path.mnt = path.mnt;
index b6f1e96..b25b154 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -887,7 +887,7 @@ EXPORT_SYMBOL(dentry_open);
 static inline int build_open_flags(int flags, umode_t mode, struct open_flags *op)
 {
        int lookup_flags = 0;
-       int acc_mode;
+       int acc_mode = ACC_MODE(flags);
 
        if (flags & (O_CREAT | __O_TMPFILE))
                op->mode = (mode & S_IALLUGO) | S_IFREG;
@@ -909,7 +909,6 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        if (flags & __O_TMPFILE) {
                if ((flags & O_TMPFILE_MASK) != O_TMPFILE)
                        return -EINVAL;
-               acc_mode = MAY_OPEN | ACC_MODE(flags);
                if (!(acc_mode & MAY_WRITE))
                        return -EINVAL;
        } else if (flags & O_PATH) {
@@ -919,8 +918,6 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
                 */
                flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
                acc_mode = 0;
-       } else {
-               acc_mode = MAY_OPEN | ACC_MODE(flags);
        }
 
        op->open_flag = flags;