Merge branch 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 2 May 2021 16:14:01 +0000 (09:14 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 2 May 2021 16:14:01 +0000 (09:14 -0700)
Pull misc vfs updates from Al Viro:
 "Assorted stuff all over the place"

* 'work.misc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  useful constants: struct qstr for ".."
  hostfs_open(): don't open-code file_dentry()
  whack-a-mole: kill strlen_user() (again)
  autofs: should_expire() argument is guaranteed to be positive
  apparmor:match_mn() - constify devpath argument
  buffer: a small optimization in grow_buffers
  get rid of autofs_getpath()
  constify dentry argument of dentry_path()/dentry_path_raw()

22 files changed:
arch/csky/include/asm/uaccess.h
arch/csky/lib/usercopy.c
arch/nds32/include/asm/uaccess.h
arch/nios2/include/asm/uaccess.h
arch/riscv/include/asm/uaccess.h
fs/autofs/autofs_i.h
fs/autofs/expire.c
fs/autofs/waitq.c
fs/buffer.c
fs/d_path.c
fs/dcache.c
fs/ext2/namei.c
fs/ext4/namei.c
fs/f2fs/dir.c
fs/f2fs/namei.c
fs/fuse/inode.c
fs/hostfs/hostfs_kern.c
fs/nilfs2/namei.c
fs/udf/namei.c
fs/ufs/super.c
include/linux/dcache.h
security/apparmor/mount.c

index 3dec272..4216a2a 100644 (file)
@@ -397,8 +397,6 @@ long __strncpy_from_user(char *dst, const char *src, long count);
  */
 long strnlen_user(const char *src, long n);
 
-#define strlen_user(str) strnlen_user(str, 32767)
-
 struct exception_table_entry {
        unsigned long insn;
        unsigned long nextinsn;
index 3c9bd64..f45b707 100644 (file)
@@ -116,7 +116,7 @@ long strncpy_from_user(char *dst, const char *src, long count)
 EXPORT_SYMBOL(strncpy_from_user);
 
 /*
- * strlen_user: - Get the size of a string in user space.
+ * strnlen_user: - Get the size of a string in user space.
  * @str: The string to measure.
  * @n:   The maximum valid length
  *
index 010ba5f..d4cbf06 100644 (file)
@@ -260,7 +260,6 @@ do {                                                                        \
 
 extern unsigned long __arch_clear_user(void __user * addr, unsigned long n);
 extern long strncpy_from_user(char *dest, const char __user * src, long count);
-extern __must_check long strlen_user(const char __user * str);
 extern __must_check long strnlen_user(const char __user * str, long n);
 extern unsigned long __arch_copy_from_user(void *to, const void __user * from,
                                            unsigned long n);
index a741abb..ba9340e 100644 (file)
@@ -83,7 +83,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n);
 
 extern long strncpy_from_user(char *__to, const char __user *__from,
                              long __len);
-extern __must_check long strlen_user(const char __user *str);
 extern __must_check long strnlen_user(const char __user *s, long n);
 
 /* Optimized macros */
index f944062..f314ff4 100644 (file)
@@ -375,7 +375,6 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 
 extern long strncpy_from_user(char *dest, const char __user *src, long count);
 
-extern long __must_check strlen_user(const char __user *str);
 extern long __must_check strnlen_user(const char __user *str, long n);
 
 extern
index 054f97b..918826e 100644 (file)
@@ -87,6 +87,7 @@ struct autofs_wait_queue {
        autofs_wqt_t wait_queue_token;
        /* We use the following to see what we are waiting for */
        struct qstr name;
+       u32 offset;
        u32 dev;
        u64 ino;
        kuid_t uid;
index a1c7701..b3fefd6 100644 (file)
@@ -355,7 +355,7 @@ static struct dentry *should_expire(struct dentry *dentry,
                return NULL;
        }
 
-       if (d_really_is_positive(dentry) && d_is_symlink(dentry)) {
+       if (d_is_symlink(dentry)) {
                pr_debug("checking symlink %p %pd\n", dentry, dentry);
 
                /* Forced expire, user space handles busy mounts */
index 5ced859..16b5fca 100644 (file)
@@ -30,7 +30,7 @@ void autofs_catatonic_mode(struct autofs_sb_info *sbi)
        while (wq) {
                nwq = wq->next;
                wq->status = -ENOENT; /* Magic is gone - report failure */
-               kfree(wq->name.name);
+               kfree(wq->name.name - wq->offset);
                wq->name.name = NULL;
                wq->wait_ctr--;
                wake_up_interruptible(&wq->queue);
@@ -175,51 +175,6 @@ static void autofs_notify_daemon(struct autofs_sb_info *sbi,
        fput(pipe);
 }
 
-static int autofs_getpath(struct autofs_sb_info *sbi,
-                         struct dentry *dentry, char *name)
-{
-       struct dentry *root = sbi->sb->s_root;
-       struct dentry *tmp;
-       char *buf;
-       char *p;
-       int len;
-       unsigned seq;
-
-rename_retry:
-       buf = name;
-       len = 0;
-
-       seq = read_seqbegin(&rename_lock);
-       rcu_read_lock();
-       spin_lock(&sbi->fs_lock);
-       for (tmp = dentry ; tmp != root ; tmp = tmp->d_parent)
-               len += tmp->d_name.len + 1;
-
-       if (!len || --len > NAME_MAX) {
-               spin_unlock(&sbi->fs_lock);
-               rcu_read_unlock();
-               if (read_seqretry(&rename_lock, seq))
-                       goto rename_retry;
-               return 0;
-       }
-
-       *(buf + len) = '\0';
-       p = buf + len - dentry->d_name.len;
-       strncpy(p, dentry->d_name.name, dentry->d_name.len);
-
-       for (tmp = dentry->d_parent; tmp != root ; tmp = tmp->d_parent) {
-               *(--p) = '/';
-               p -= tmp->d_name.len;
-               strncpy(p, tmp->d_name.name, tmp->d_name.len);
-       }
-       spin_unlock(&sbi->fs_lock);
-       rcu_read_unlock();
-       if (read_seqretry(&rename_lock, seq))
-               goto rename_retry;
-
-       return len;
-}
-
 static struct autofs_wait_queue *
 autofs_find_wait(struct autofs_sb_info *sbi, const struct qstr *qstr)
 {
@@ -352,6 +307,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
        struct qstr qstr;
        char *name;
        int status, ret, type;
+       unsigned int offset = 0;
        pid_t pid;
        pid_t tgid;
 
@@ -389,20 +345,23 @@ int autofs_wait(struct autofs_sb_info *sbi,
                return -ENOMEM;
 
        /* If this is a direct mount request create a dummy name */
-       if (IS_ROOT(dentry) && autofs_type_trigger(sbi->type))
+       if (IS_ROOT(dentry) && autofs_type_trigger(sbi->type)) {
+               qstr.name = name;
                qstr.len = sprintf(name, "%p", dentry);
-       else {
-               qstr.len = autofs_getpath(sbi, dentry, name);
-               if (!qstr.len) {
+       else {
+               char *p = dentry_path_raw(dentry, name, NAME_MAX);
+               if (IS_ERR(p)) {
                        kfree(name);
                        return -ENOENT;
                }
+               qstr.name = ++p; // skip the leading slash
+               qstr.len = strlen(p);
+               offset = p - name;
        }
-       qstr.name = name;
        qstr.hash = full_name_hash(dentry, name, qstr.len);
 
        if (mutex_lock_interruptible(&sbi->wq_mutex)) {
-               kfree(qstr.name);
+               kfree(name);
                return -EINTR;
        }
 
@@ -410,7 +369,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
        if (ret <= 0) {
                if (ret != -EINTR)
                        mutex_unlock(&sbi->wq_mutex);
-               kfree(qstr.name);
+               kfree(name);
                return ret;
        }
 
@@ -418,7 +377,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                /* Create a new wait queue */
                wq = kmalloc(sizeof(struct autofs_wait_queue), GFP_KERNEL);
                if (!wq) {
-                       kfree(qstr.name);
+                       kfree(name);
                        mutex_unlock(&sbi->wq_mutex);
                        return -ENOMEM;
                }
@@ -430,6 +389,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                sbi->queues = wq;
                init_waitqueue_head(&wq->queue);
                memcpy(&wq->name, &qstr, sizeof(struct qstr));
+               wq->offset = offset;
                wq->dev = autofs_get_dev(sbi);
                wq->ino = autofs_get_ino(sbi);
                wq->uid = current_uid();
@@ -469,7 +429,7 @@ int autofs_wait(struct autofs_sb_info *sbi,
                         (unsigned long) wq->wait_queue_token, wq->name.len,
                         wq->name.name, notify);
                mutex_unlock(&sbi->wq_mutex);
-               kfree(qstr.name);
+               kfree(name);
        }
 
        /*
@@ -540,7 +500,7 @@ int autofs_wait_release(struct autofs_sb_info *sbi,
        }
 
        *wql = wq->next;        /* Unlink from chain */
-       kfree(wq->name.name);
+       kfree(wq->name.name - wq->offset);
        wq->name.name = NULL;   /* Do not wait on this queue */
        wq->status = status;
        wake_up(&wq->queue);
index 0cb7ffd..c2e052c 100644 (file)
@@ -1020,11 +1020,7 @@ grow_buffers(struct block_device *bdev, sector_t block, int size, gfp_t gfp)
        pgoff_t index;
        int sizebits;
 
-       sizebits = -1;
-       do {
-               sizebits++;
-       } while ((size << sizebits) < PAGE_SIZE);
-
+       sizebits = PAGE_SHIFT - __ffs(size);
        index = block >> sizebits;
 
        /*
index a69e2cd..270d621 100644 (file)
@@ -326,9 +326,9 @@ char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
 /*
  * Write full pathname from the root of the filesystem into the buffer.
  */
-static char *__dentry_path(struct dentry *d, char *buf, int buflen)
+static char *__dentry_path(const struct dentry *d, char *buf, int buflen)
 {
-       struct dentry *dentry;
+       const struct dentry *dentry;
        char *end, *retval;
        int len, seq = 0;
        int error = 0;
@@ -347,7 +347,7 @@ restart:
        *retval = '/';
        read_seqbegin_or_lock(&rename_lock, &seq);
        while (!IS_ROOT(dentry)) {
-               struct dentry *parent = dentry->d_parent;
+               const struct dentry *parent = dentry->d_parent;
 
                prefetch(parent);
                error = prepend_name(&end, &len, &dentry->d_name);
@@ -371,13 +371,13 @@ Elong:
        return ERR_PTR(-ENAMETOOLONG);
 }
 
-char *dentry_path_raw(struct dentry *dentry, char *buf, int buflen)
+char *dentry_path_raw(const struct dentry *dentry, char *buf, int buflen)
 {
        return __dentry_path(dentry, buf, buflen);
 }
 EXPORT_SYMBOL(dentry_path_raw);
 
-char *dentry_path(struct dentry *dentry, char *buf, int buflen)
+char *dentry_path(const struct dentry *dentry, char *buf, int buflen)
 {
        char *p = NULL;
        char *retval;
index 7d24ff7..cf871a8 100644 (file)
@@ -84,6 +84,8 @@ const struct qstr empty_name = QSTR_INIT("", 0);
 EXPORT_SYMBOL(empty_name);
 const struct qstr slash_name = QSTR_INIT("/", 1);
 EXPORT_SYMBOL(slash_name);
+const struct qstr dotdot_name = QSTR_INIT("..", 2);
+EXPORT_SYMBOL(dotdot_name);
 
 /*
  * This is the single most critical data structure when it comes
index c6b8bba..1f69b81 100644 (file)
@@ -81,11 +81,10 @@ static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, uns
 
 struct dentry *ext2_get_parent(struct dentry *child)
 {
-       struct qstr dotdot = QSTR_INIT("..", 2);
        ino_t ino;
        int res;
 
-       res = ext2_inode_by_name(d_inode(child), &dotdot, &ino);
+       res = ext2_inode_by_name(d_inode(child), &dotdot_name, &ino);
        if (res)
                return ERR_PTR(res);
 
index e8100a9..afb9d05 100644 (file)
@@ -1814,11 +1814,10 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
 struct dentry *ext4_get_parent(struct dentry *child)
 {
        __u32 ino;
-       static const struct qstr dotdot = QSTR_INIT("..", 2);
        struct ext4_dir_entry_2 * de;
        struct buffer_head *bh;
 
-       bh = ext4_find_entry(d_inode(child), &dotdot, &de, NULL);
+       bh = ext4_find_entry(d_inode(child), &dotdot_name, &de, NULL);
        if (IS_ERR(bh))
                return ERR_CAST(bh);
        if (!bh)
index e6270a8..e211a1b 100644 (file)
@@ -449,9 +449,7 @@ struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir,
 
 struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p)
 {
-       struct qstr dotdot = QSTR_INIT("..", 2);
-
-       return f2fs_find_entry(dir, &dotdot, p);
+       return f2fs_find_entry(dir, &dotdot_name, p);
 }
 
 ino_t f2fs_inode_by_name(struct inode *dir, const struct qstr *qstr,
index 14bf4f6..377c6b1 100644 (file)
@@ -416,9 +416,8 @@ out:
 
 struct dentry *f2fs_get_parent(struct dentry *child)
 {
-       struct qstr dotdot = QSTR_INIT("..", 2);
        struct page *page;
-       unsigned long ino = f2fs_inode_by_name(d_inode(child), &dotdot, &page);
+       unsigned long ino = f2fs_inode_by_name(d_inode(child), &dotdot_name, &page);
        if (!ino) {
                if (IS_ERR(page))
                        return ERR_CAST(page);
index 6c99520..393e36b 100644 (file)
@@ -873,14 +873,13 @@ static struct dentry *fuse_get_parent(struct dentry *child)
        struct inode *inode;
        struct dentry *parent;
        struct fuse_entry_out outarg;
-       const struct qstr name = QSTR_INIT("..", 2);
        int err;
 
        if (!fc->export_support)
                return ERR_PTR(-ESTALE);
 
        err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode),
-                              &name, &outarg, &inode);
+                              &dotdot_name, &outarg, &inode);
        if (err) {
                if (err == -ENOENT)
                        return ERR_PTR(-ESTALE);
index 7b5e984..7d0c3db 100644 (file)
@@ -316,7 +316,7 @@ retry:
        if (mode & FMODE_WRITE)
                r = w = 1;
 
-       name = dentry_name(d_real(file->f_path.dentry, file->f_inode));
+       name = dentry_name(file_dentry(file));
        if (name == NULL)
                return -ENOMEM;
 
index 189bd10..91eebeb 100644 (file)
@@ -440,10 +440,9 @@ static struct dentry *nilfs_get_parent(struct dentry *child)
 {
        unsigned long ino;
        struct inode *inode;
-       struct qstr dotdot = QSTR_INIT("..", 2);
        struct nilfs_root *root;
 
-       ino = nilfs_inode_by_name(d_inode(child), &dotdot);
+       ino = nilfs_inode_by_name(d_inode(child), &dotdot_name);
        if (!ino)
                return ERR_PTR(-ENOENT);
 
index f146b30..3ae9f1e 100644 (file)
@@ -1215,11 +1215,10 @@ static struct dentry *udf_get_parent(struct dentry *child)
 {
        struct kernel_lb_addr tloc;
        struct inode *inode = NULL;
-       struct qstr dotdot = QSTR_INIT("..", 2);
        struct fileIdentDesc cfi;
        struct udf_fileident_bh fibh;
 
-       if (!udf_find_entry(d_inode(child), &dotdot, &fibh, &cfi))
+       if (!udf_find_entry(d_inode(child), &dotdot_name, &fibh, &cfi))
                return ERR_PTR(-EACCES);
 
        if (fibh.sbh != fibh.ebh)
index 983558b..74028b5 100644 (file)
@@ -128,10 +128,9 @@ static struct dentry *ufs_fh_to_parent(struct super_block *sb, struct fid *fid,
 
 static struct dentry *ufs_get_parent(struct dentry *child)
 {
-       struct qstr dot_dot = QSTR_INIT("..", 2);
        ino_t ino;
 
-       ino = ufs_inode_by_name(d_inode(child), &dot_dot);
+       ino = ufs_inode_by_name(d_inode(child), &dotdot_name);
        if (!ino)
                return ERR_PTR(-ENOENT);
        return d_obtain_alias(ufs_iget(child->d_sb, ino));
index c1e4801..9e23d33 100644 (file)
@@ -59,6 +59,7 @@ struct qstr {
 
 extern const struct qstr empty_name;
 extern const struct qstr slash_name;
+extern const struct qstr dotdot_name;
 
 struct dentry_stat_t {
        long nr_dentry;
@@ -300,8 +301,8 @@ char *dynamic_dname(struct dentry *, char *, int, const char *, ...);
 extern char *__d_path(const struct path *, const struct path *, char *, int);
 extern char *d_absolute_path(const struct path *, char *, int);
 extern char *d_path(const struct path *, char *, int);
-extern char *dentry_path_raw(struct dentry *, char *, int);
-extern char *dentry_path(struct dentry *, char *, int);
+extern char *dentry_path_raw(const struct dentry *, char *, int);
+extern char *dentry_path(const struct dentry *, char *, int);
 
 /* Allocation counts.. */
 
index e0828ee..aa6fcfd 100644 (file)
@@ -370,7 +370,7 @@ audit:
  * Returns: 0 on success else error
  */
 static int match_mnt(struct aa_profile *profile, const struct path *path,
-                    char *buffer, struct path *devpath, char *devbuffer,
+                    char *buffer, const struct path *devpath, char *devbuffer,
                     const char *type, unsigned long flags, void *data,
                     bool binary)
 {
@@ -579,7 +579,7 @@ out:
        return error;
 }
 
-static int profile_umount(struct aa_profile *profile, struct path *path,
+static int profile_umount(struct aa_profile *profile, const struct path *path,
                          char *buffer)
 {
        struct aa_perms perms = { };