summaryrefslogtreecommitdiff
path: root/fs/namei.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2013-10-04 19:15:13 -0700
committerAl Viro <viro@zeniv.linux.org.uk>2014-10-09 02:38:54 -0400
commit7af1364ffa64db61e386628594836e13d2ef04b5 (patch)
tree45f295668d231d1c1a7a063d16195035cac467cf /fs/namei.c
parentbafc9b754f752ea798c39f9b099a228fd56604e0 (diff)
downloadlwn-7af1364ffa64db61e386628594836e13d2ef04b5.tar.gz
lwn-7af1364ffa64db61e386628594836e13d2ef04b5.zip
vfs: Don't allow overwriting mounts in the current mount namespace
In preparation for allowing mountpoints to be renamed and unlinked in remote filesystems and in other mount namespaces test if on a dentry there is a mount in the local mount namespace before allowing it to be renamed or unlinked. The primary motivation here are old versions of fusermount unmount which is not safe if the a path can be renamed or unlinked while it is verifying the mount is safe to unmount. More recent versions are simpler and safer by simply using UMOUNT_NOFOLLOW when unmounting a mount in a directory owned by an arbitrary user. Miklos Szeredi <miklos@szeredi.hu> reports this is approach is good enough to remove concerns about new kernels mixed with old versions of fusermount. A secondary motivation for restrictions here is that it removing empty directories that have non-empty mount points on them appears to violate the rule that rmdir can not remove empty directories. As Linus Torvalds pointed out this is useful for programs (like git) that test if a directory is empty with rmdir. Therefore this patch arranges to enforce the existing mount point semantics for local mount namespace. v2: Rewrote the test to be a drop in replacement for d_mountpoint v3: Use bool instead of int as the return type of is_local_mountpoint Reviewed-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/fs/namei.c b/fs/namei.c
index a7b05bf82d31..a3a14b033b0d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3565,6 +3565,8 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
mutex_lock(&dentry->d_inode->i_mutex);
error = -EBUSY;
+ if (is_local_mountpoint(dentry))
+ goto out;
if (d_mountpoint(dentry))
goto out;
@@ -3681,7 +3683,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry, struct inode **delegate
return -EPERM;
mutex_lock(&target->i_mutex);
- if (d_mountpoint(dentry))
+ if (is_local_mountpoint(dentry) || d_mountpoint(dentry))
error = -EBUSY;
else {
error = security_inode_unlink(dir, dentry);
@@ -4126,6 +4128,8 @@ int vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
mutex_lock(&target->i_mutex);
error = -EBUSY;
+ if (is_local_mountpoint(old_dentry) || is_local_mountpoint(new_dentry))
+ goto out;
if (d_mountpoint(old_dentry) || d_mountpoint(new_dentry))
goto out;