use new neg dentry checks. extra tests in rename
authorErez Zadok <ezk@cs.sunysb.edu>
Sun, 15 Dec 2019 02:54:39 +0000 (21:54 -0500)
committerErez Zadok <ezk@cs.sunysb.edu>
Sun, 15 Dec 2019 02:54:39 +0000 (21:54 -0500)
fs/wrapfs/inode.c

index dba9328108bb816177df1bcd40969bef8f7393d5..447b44f4c45d173bc3b6ae4de03383dd7595ac61 100644 (file)
@@ -58,7 +58,7 @@ static int wrapfs_link(struct dentry *old_dentry, struct inode *dir,
 
        err = vfs_link(lower_old_dentry, d_inode(lower_dir_dentry),
                       lower_new_dentry, NULL);
-       if (err || !d_inode(lower_new_dentry))
+       if (err || d_really_is_negative(lower_new_dentry))
                goto out;
 
        err = wrapfs_interpose(new_dentry, dir->i_sb, &lower_new_path);
@@ -255,11 +255,18 @@ static int wrapfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        lower_new_dir_dentry = dget_parent(lower_new_dentry);
 
        trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
+       err = -EINVAL;
+       /* check for unexpected namespace changes */
+       if (lower_old_dentry->d_parent != lower_old_dir_dentry)
+               goto out;
+       if (lower_new_dentry->d_parent != lower_new_dir_dentry)
+               goto out;
+       /* check if either dentry got unlinked */
+       if (d_unhashed(lower_old_dentry) || d_unhashed(lower_new_dentry))
+               goto out;
        /* source should not be ancestor of target */
-       if (trap == lower_old_dentry) {
-               err = -EINVAL;
+       if (trap == lower_old_dentry)
                goto out;
-       }
        /* target should not be ancestor of source */
        if (trap == lower_new_dentry) {
                err = -ENOTEMPTY;