affs_lookup: switch to d_splice_alias()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 6 May 2018 16:20:40 +0000 (12:20 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 21 May 2018 18:29:12 +0000 (14:29 -0400)
Making something exportable takes more than providing ->s_export_ops.
In particular, ->lookup() *MUST* use d_splice_alias() instead of
d_add().

Reading Documentation/filesystems/nfs/Exporting would've been a good idea;
as it is, exporting AFFS is badly (and exploitably) broken.

Partially-Fixes: ed4433d72394 "fs/affs: make affs exportable"
Acked-by: David Sterba <dsterba@suse.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/affs/namei.c

index 1ed0fa4c4d481842c22ac4a3a95f5b867c84f53d..41c5749f4db78078b2e1d5b65c31aa0b2c7724c1 100644 (file)
@@ -201,6 +201,7 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
        struct super_block *sb = dir->i_sb;
        struct buffer_head *bh;
        struct inode *inode = NULL;
        struct super_block *sb = dir->i_sb;
        struct buffer_head *bh;
        struct inode *inode = NULL;
+       struct dentry *res;
 
        pr_debug("%s(\"%pd\")\n", __func__, dentry);
 
 
        pr_debug("%s(\"%pd\")\n", __func__, dentry);
 
@@ -223,14 +224,12 @@ affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
                }
                affs_brelse(bh);
                inode = affs_iget(sb, ino);
                }
                affs_brelse(bh);
                inode = affs_iget(sb, ino);
-               if (IS_ERR(inode)) {
-                       affs_unlock_dir(dir);
-                       return ERR_CAST(inode);
-               }
        }
        }
-       d_add(dentry, inode);
+       res = d_splice_alias(inode, dentry);
+       if (!IS_ERR_OR_NULL(res))
+               res->d_fsdata = dentry->d_fsdata;
        affs_unlock_dir(dir);
        affs_unlock_dir(dir);
-       return NULL;
+       return res;
 }
 
 int
 }
 
 int