Merge branch 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Sep 2019 20:03:01 +0000 (13:03 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 18 Sep 2019 20:03:01 +0000 (13:03 -0700)
Pull vfs namei updates from Al Viro:
 "Pathwalk-related stuff"

[ Audit-related cleanups, misc simplifications, and easier to follow
  nd->root refcounts     - Linus ]

* 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  devpts_pty_kill(): don't bother with d_delete()
  infiniband: don't bother with d_delete()
  hypfs: don't bother with d_delete()
  fs/namei.c: keep track of nd->root refcount status
  fs/namei.c: new helper - legitimize_root()
  kill the last users of user_{path,lpath,path_dir}()
  namei.h: get the comments on LOOKUP_... in sync with reality
  kill LOOKUP_NO_EVAL, don't bother including namei.h from audit.h
  audit_inode(): switch to passing AUDIT_INODE_...
  filename_mountpoint(): make LOOKUP_NO_EVAL unconditional there
  filename_lookup(): audit_inode() argument is always 0

arch/s390/hypfs/inode.c
drivers/infiniband/hw/qib/qib_fs.c
fs/coda/pioctl.c
fs/devpts/inode.c
fs/namei.c
fs/namespace.c
fs/nfs/nfstrace.h
fs/xfs/xfs_ioctl.c
include/linux/audit.h
include/linux/namei.h

index ccad1398abd406eba3298cc85bec320161443566..a4418fc425b8d23d46128d8477f7af56e64bc2ad 100644 (file)
@@ -76,7 +76,7 @@ static void hypfs_remove(struct dentry *dentry)
                else
                        simple_unlink(d_inode(parent), dentry);
        }
-       d_delete(dentry);
+       d_drop(dentry);
        dput(dentry);
        inode_unlock(d_inode(parent));
 }
index 41a569558a1579908e8fdf0f5164d8c703ddd7b3..e336d778e076eddb3d56c37b6fd33be0de87b050 100644 (file)
@@ -493,7 +493,7 @@ static int remove_device_files(struct super_block *sb,
        remove_file(dir, "flash");
        inode_unlock(d_inode(dir));
        ret = simple_rmdir(d_inode(root), dir);
-       d_delete(dir);
+       d_drop(dir);
        dput(dir);
 
 bail:
index 644d48c12ce827cd36a44828ac377aecdb41bfcb..3aec27e5eb82dbb6c1798d908cacad749d02e61b 100644 (file)
@@ -63,11 +63,8 @@ static long coda_pioctl(struct file *filp, unsigned int cmd,
         * Look up the pathname. Note that the pathname is in
         * user memory, and namei takes care of this
         */
-       if (data.follow)
-               error = user_path(data.path, &path);
-       else
-               error = user_lpath(data.path, &path);
-
+       error = user_path_at(AT_FDCWD, data.path,
+                            data.follow ? LOOKUP_FOLLOW : 0, &path);
        if (error)
                return error;
 
index beeadca23b05c85f5171c18d240f9580f496f1e4..42e5a766d33c7d1fea3ca9c05be73639c38c421e 100644 (file)
@@ -622,7 +622,7 @@ void devpts_pty_kill(struct dentry *dentry)
        dentry->d_fsdata = NULL;
        drop_nlink(dentry->d_inode);
        fsnotify_unlink(d_inode(dentry->d_parent), dentry);
-       d_delete(dentry);
+       d_drop(dentry);
        dput(dentry);   /* d_alloc_name() in devpts_pty_new() */
 }
 
index 209c51a5226c9cf1529e50c9696d09c469c3e2ab..671c3c1a3425bab83d07a6b1091360dc7d03b9f0 100644 (file)
@@ -596,14 +596,12 @@ static void terminate_walk(struct nameidata *nd)
                path_put(&nd->path);
                for (i = 0; i < nd->depth; i++)
                        path_put(&nd->stack[i].link);
-               if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
+               if (nd->flags & LOOKUP_ROOT_GRABBED) {
                        path_put(&nd->root);
-                       nd->root.mnt = NULL;
+                       nd->flags &= ~LOOKUP_ROOT_GRABBED;
                }
        } else {
                nd->flags &= ~LOOKUP_RCU;
-               if (!(nd->flags & LOOKUP_ROOT))
-                       nd->root.mnt = NULL;
                rcu_read_unlock();
        }
        nd->depth = 0;
@@ -641,6 +639,14 @@ static bool legitimize_links(struct nameidata *nd)
        return true;
 }
 
+static bool legitimize_root(struct nameidata *nd)
+{
+       if (!nd->root.mnt || (nd->flags & LOOKUP_ROOT))
+               return true;
+       nd->flags |= LOOKUP_ROOT_GRABBED;
+       return legitimize_path(nd, &nd->root, nd->root_seq);
+}
+
 /*
  * Path walking has 2 modes, rcu-walk and ref-walk (see
  * Documentation/filesystems/path-lookup.txt).  In situations when we can't
@@ -671,23 +677,18 @@ static int unlazy_walk(struct nameidata *nd)
 
        nd->flags &= ~LOOKUP_RCU;
        if (unlikely(!legitimize_links(nd)))
-               goto out2;
-       if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
                goto out1;
-       if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
-               if (unlikely(!legitimize_path(nd, &nd->root, nd->root_seq)))
-                       goto out;
-       }
+       if (unlikely(!legitimize_path(nd, &nd->path, nd->seq)))
+               goto out;
+       if (unlikely(!legitimize_root(nd)))
+               goto out;
        rcu_read_unlock();
        BUG_ON(nd->inode != parent->d_inode);
        return 0;
 
-out2:
+out1:
        nd->path.mnt = NULL;
        nd->path.dentry = NULL;
-out1:
-       if (!(nd->flags & LOOKUP_ROOT))
-               nd->root.mnt = NULL;
 out:
        rcu_read_unlock();
        return -ECHILD;
@@ -727,23 +728,14 @@ static int unlazy_child(struct nameidata *nd, struct dentry *dentry, unsigned se
         */
        if (unlikely(!lockref_get_not_dead(&dentry->d_lockref)))
                goto out;
-       if (unlikely(read_seqcount_retry(&dentry->d_seq, seq))) {
-               rcu_read_unlock();
-               dput(dentry);
-               goto drop_root_mnt;
-       }
+       if (unlikely(read_seqcount_retry(&dentry->d_seq, seq)))
+               goto out_dput;
        /*
         * Sequence counts matched. Now make sure that the root is
         * still valid and get it if required.
         */
-       if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT)) {
-               if (unlikely(!legitimize_path(nd, &nd->root, nd->root_seq))) {
-                       rcu_read_unlock();
-                       dput(dentry);
-                       return -ECHILD;
-               }
-       }
-
+       if (unlikely(!legitimize_root(nd)))
+               goto out_dput;
        rcu_read_unlock();
        return 0;
 
@@ -753,9 +745,10 @@ out1:
        nd->path.dentry = NULL;
 out:
        rcu_read_unlock();
-drop_root_mnt:
-       if (!(nd->flags & LOOKUP_ROOT))
-               nd->root.mnt = NULL;
+       return -ECHILD;
+out_dput:
+       rcu_read_unlock();
+       dput(dentry);
        return -ECHILD;
 }
 
@@ -819,6 +812,7 @@ static void set_root(struct nameidata *nd)
                } while (read_seqcount_retry(&fs->seq, seq));
        } else {
                get_fs_root(fs, &nd->root);
+               nd->flags |= LOOKUP_ROOT_GRABBED;
        }
 }
 
@@ -1735,8 +1729,6 @@ static int pick_link(struct nameidata *nd, struct path *link,
                                nd->flags &= ~LOOKUP_RCU;
                                nd->path.mnt = NULL;
                                nd->path.dentry = NULL;
-                               if (!(nd->flags & LOOKUP_ROOT))
-                                       nd->root.mnt = NULL;
                                rcu_read_unlock();
                        } else if (likely(unlazy_walk(nd)) == 0)
                                error = nd_alloc_stack(nd);
@@ -2350,7 +2342,7 @@ int filename_lookup(int dfd, struct filename *name, unsigned flags,
                retval = path_lookupat(&nd, flags | LOOKUP_REVAL, path);
 
        if (likely(!retval))
-               audit_inode(name, path->dentry, flags & LOOKUP_PARENT);
+               audit_inode(name, path->dentry, 0);
        restore_nameidata();
        putname(name);
        return retval;
@@ -2391,7 +2383,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
        if (likely(!retval)) {
                *last = nd.last;
                *type = nd.last_type;
-               audit_inode(name, parent->dentry, LOOKUP_PARENT);
+               audit_inode(name, parent->dentry, AUDIT_INODE_PARENT);
        } else {
                putname(name);
                name = ERR_PTR(retval);
@@ -2718,7 +2710,7 @@ filename_mountpoint(int dfd, struct filename *name, struct path *path,
        if (unlikely(error == -ESTALE))
                error = path_mountpoint(&nd, flags | LOOKUP_REVAL, path);
        if (likely(!error))
-               audit_inode(name, path->dentry, flags & LOOKUP_NO_EVAL);
+               audit_inode(name, path->dentry, AUDIT_INODE_NOEVAL);
        restore_nameidata();
        putname(name);
        return error;
@@ -3299,7 +3291,7 @@ static int do_last(struct nameidata *nd,
                if (error)
                        return error;
 
-               audit_inode(nd->name, dir, LOOKUP_PARENT);
+               audit_inode(nd->name, dir, AUDIT_INODE_PARENT);
                /* trailing slashes? */
                if (unlikely(nd->last.name[nd->last.len]))
                        return -EISDIR;
index d28d30b1304397eac7c92a4be3f60e02a9a536d7..81edb7e7ddfda8840e233fd2ead048b3d35377d0 100644 (file)
@@ -1675,8 +1675,6 @@ int ksys_umount(char __user *name, int flags)
        if (!(flags & UMOUNT_NOFOLLOW))
                lookup_flags |= LOOKUP_FOLLOW;
 
-       lookup_flags |= LOOKUP_NO_EVAL;
-
        retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
        if (retval)
                goto out;
@@ -3046,7 +3044,7 @@ long do_mount(const char *dev_name, const char __user *dir_name,
                return -EINVAL;
 
        /* ... and get the mountpoint */
-       retval = user_path(dir_name, &path);
+       retval = user_path_at(AT_FDCWD, dir_name, LOOKUP_FOLLOW, &path);
        if (retval)
                return retval;
 
@@ -3593,11 +3591,13 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
        if (!may_mount())
                return -EPERM;
 
-       error = user_path_dir(new_root, &new);
+       error = user_path_at(AT_FDCWD, new_root,
+                            LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &new);
        if (error)
                goto out0;
 
-       error = user_path_dir(put_old, &old);
+       error = user_path_at(AT_FDCWD, put_old,
+                            LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &old);
        if (error)
                goto out1;
 
index 976d4089e2678a407d533d3eb53192e5151493a1..361cc10d6f95ddfcc993baabfa5257189a466a84 100644 (file)
@@ -207,7 +207,6 @@ TRACE_DEFINE_ENUM(LOOKUP_PARENT);
 TRACE_DEFINE_ENUM(LOOKUP_REVAL);
 TRACE_DEFINE_ENUM(LOOKUP_RCU);
 TRACE_DEFINE_ENUM(LOOKUP_NO_REVAL);
-TRACE_DEFINE_ENUM(LOOKUP_NO_EVAL);
 TRACE_DEFINE_ENUM(LOOKUP_OPEN);
 TRACE_DEFINE_ENUM(LOOKUP_CREATE);
 TRACE_DEFINE_ENUM(LOOKUP_EXCL);
@@ -226,7 +225,6 @@ TRACE_DEFINE_ENUM(LOOKUP_DOWN);
                        { LOOKUP_REVAL, "REVAL" }, \
                        { LOOKUP_RCU, "RCU" }, \
                        { LOOKUP_NO_REVAL, "NO_REVAL" }, \
-                       { LOOKUP_NO_EVAL, "NO_EVAL" }, \
                        { LOOKUP_OPEN, "OPEN" }, \
                        { LOOKUP_CREATE, "CREATE" }, \
                        { LOOKUP_EXCL, "EXCL" }, \
index 6f7848cd5527bc8d32c840c44d4748a1422357fb..affa557c233704bc327cff86a851471ccfef586b 100644 (file)
@@ -67,7 +67,7 @@ xfs_find_handle(
                        return -EBADF;
                inode = file_inode(f.file);
        } else {
-               error = user_lpath((const char __user *)hreq->path, &path);
+               error = user_path_at(AT_FDCWD, hreq->path, 0, &path);
                if (error)
                        return error;
                inode = d_inode(path.dentry);
index 97d0925454dff33cac393801dea7a3c8a885786f..aee3dc9eb378ec3ec69ea428975375a0758c1fb4 100644 (file)
@@ -11,7 +11,6 @@
 
 #include <linux/sched.h>
 #include <linux/ptrace.h>
-#include <linux/namei.h>  /* LOOKUP_* */
 #include <uapi/linux/audit.h>
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
@@ -252,6 +251,10 @@ static inline int audit_signal_info(int sig, struct task_struct *t)
 #define audit_is_compat(arch)  false
 #endif
 
+#define AUDIT_INODE_PARENT     1       /* dentry represents the parent */
+#define AUDIT_INODE_HIDDEN     2       /* audit record should be hidden */
+#define AUDIT_INODE_NOEVAL     4       /* audit record incomplete */
+
 #ifdef CONFIG_AUDITSYSCALL
 #include <asm/syscall.h> /* for syscall_get_arch() */
 
@@ -265,9 +268,6 @@ extern void __audit_syscall_exit(int ret_success, long ret_value);
 extern struct filename *__audit_reusename(const __user char *uptr);
 extern void __audit_getname(struct filename *name);
 
-#define AUDIT_INODE_PARENT     1       /* dentry represents the parent */
-#define AUDIT_INODE_HIDDEN     2       /* audit record should be hidden */
-#define AUDIT_INODE_NOEVAL     4       /* audit record incomplete */
 extern void __audit_inode(struct filename *name, const struct dentry *dentry,
                                unsigned int flags);
 extern void __audit_file(const struct file *);
@@ -328,16 +328,9 @@ static inline void audit_getname(struct filename *name)
 }
 static inline void audit_inode(struct filename *name,
                                const struct dentry *dentry,
-                               unsigned int flags) {
-       if (unlikely(!audit_dummy_context())) {
-               unsigned int aflags = 0;
-
-               if (flags & LOOKUP_PARENT)
-                       aflags |= AUDIT_INODE_PARENT;
-               if (flags & LOOKUP_NO_EVAL)
-                       aflags |= AUDIT_INODE_NOEVAL;
+                               unsigned int aflags) {
+       if (unlikely(!audit_dummy_context()))
                __audit_inode(name, dentry, aflags);
-       }
 }
 static inline void audit_file(struct file *file)
 {
@@ -561,7 +554,7 @@ static inline void __audit_inode_child(struct inode *parent,
 { }
 static inline void audit_inode(struct filename *name,
                                const struct dentry *dentry,
-                               unsigned int parent)
+                               unsigned int aflags)
 { }
 static inline void audit_file(struct file *file)
 {
index 9138b4471dbfc250d0811615f87b78b58053bdc1..397a08ade6a2108818498a71912ec31e97e0bebb 100644 (file)
@@ -16,39 +16,28 @@ enum { MAX_NESTED_LINKS = 8 };
  */
 enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 
-/*
- * The bitmask for a lookup event:
- *  - follow links at the end
- *  - require a directory
- *  - ending slashes ok even for nonexistent files
- *  - internal "there are more path components" flag
- *  - dentry cache is untrusted; force a real lookup
- *  - suppress terminal automount
- *  - skip revalidation
- *  - don't fetch xattrs on audit_inode
- */
-#define LOOKUP_FOLLOW          0x0001
-#define LOOKUP_DIRECTORY       0x0002
-#define LOOKUP_AUTOMOUNT       0x0004
-
+/* pathwalk mode */
+#define LOOKUP_FOLLOW          0x0001  /* follow links at the end */
+#define LOOKUP_DIRECTORY       0x0002  /* require a directory */
+#define LOOKUP_AUTOMOUNT       0x0004  /* force terminal automount */
+#define LOOKUP_EMPTY           0x4000  /* accept empty path [user_... only] */
+#define LOOKUP_DOWN            0x8000  /* follow mounts in the starting point */
+
+#define LOOKUP_REVAL           0x0020  /* tell ->d_revalidate() to trust no cache */
+#define LOOKUP_RCU             0x0040  /* RCU pathwalk mode; semi-internal */
+
+/* These tell filesystem methods that we are dealing with the final component... */
+#define LOOKUP_OPEN            0x0100  /* ... in open */
+#define LOOKUP_CREATE          0x0200  /* ... in object creation */
+#define LOOKUP_EXCL            0x0400  /* ... in exclusive creation */
+#define LOOKUP_RENAME_TARGET   0x0800  /* ... in destination of rename() */
+
+/* internal use only */
 #define LOOKUP_PARENT          0x0010
-#define LOOKUP_REVAL           0x0020
-#define LOOKUP_RCU             0x0040
 #define LOOKUP_NO_REVAL                0x0080
-#define LOOKUP_NO_EVAL         0x0100
-
-/*
- * Intent data
- */
-#define LOOKUP_OPEN            0x0100
-#define LOOKUP_CREATE          0x0200
-#define LOOKUP_EXCL            0x0400
-#define LOOKUP_RENAME_TARGET   0x0800
-
 #define LOOKUP_JUMPED          0x1000
 #define LOOKUP_ROOT            0x2000
-#define LOOKUP_EMPTY           0x4000
-#define LOOKUP_DOWN            0x8000
+#define LOOKUP_ROOT_GRABBED    0x0008
 
 extern int path_pts(struct path *path);
 
@@ -60,22 +49,6 @@ static inline int user_path_at(int dfd, const char __user *name, unsigned flags,
        return user_path_at_empty(dfd, name, flags, path, NULL);
 }
 
-static inline int user_path(const char __user *name, struct path *path)
-{
-       return user_path_at_empty(AT_FDCWD, name, LOOKUP_FOLLOW, path, NULL);
-}
-
-static inline int user_lpath(const char __user *name, struct path *path)
-{
-       return user_path_at_empty(AT_FDCWD, name, 0, path, NULL);
-}
-
-static inline int user_path_dir(const char __user *name, struct path *path)
-{
-       return user_path_at_empty(AT_FDCWD, name,
-                                 LOOKUP_FOLLOW | LOOKUP_DIRECTORY, path, NULL);
-}
-
 extern int kern_path(const char *, unsigned, struct path *);
 
 extern struct dentry *kern_path_create(int, const char *, struct path *, unsigned int);