Merge tag 'iio-fixes-for-3.18b' of git://git.kernel.org/pub/scm/linux/kernel/git...
[cascardo/linux.git] / fs / namei.c
index d20191c..db5fe86 100644 (file)
@@ -2497,7 +2497,7 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2)
        }
 
        mutex_lock_nested(&p1->d_inode->i_mutex, I_MUTEX_PARENT);
-       mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_CHILD);
+       mutex_lock_nested(&p2->d_inode->i_mutex, I_MUTEX_PARENT2);
        return NULL;
 }
 EXPORT_SYMBOL(lock_rename);
@@ -3154,7 +3154,8 @@ static int do_tmpfile(int dfd, struct filename *pathname,
        if (error)
                goto out2;
        audit_inode(pathname, nd->path.dentry, 0);
-       error = may_open(&nd->path, op->acc_mode, op->open_flag);
+       /* Don't check for other permissions, the inode was just created */
+       error = may_open(&nd->path, MAY_OPEN, op->open_flag);
        if (error)
                goto out2;
        file->f_path.mnt = nd->path.mnt;
@@ -4209,12 +4210,16 @@ SYSCALL_DEFINE5(renameat2, int, olddfd, const char __user *, oldname,
        bool should_retry = false;
        int error;
 
-       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE | RENAME_WHITEOUT))
                return -EINVAL;
 
-       if ((flags & RENAME_NOREPLACE) && (flags & RENAME_EXCHANGE))
+       if ((flags & (RENAME_NOREPLACE | RENAME_WHITEOUT)) &&
+           (flags & RENAME_EXCHANGE))
                return -EINVAL;
 
+       if ((flags & RENAME_WHITEOUT) && !capable(CAP_MKNOD))
+               return -EPERM;
+
 retry:
        from = user_path_parent(olddfd, oldname, &oldnd, lookup_flags);
        if (IS_ERR(from)) {