Quoting Eric W. Biederman (ebiederm@xxxxxxxxxxxx): > > 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@xxxxxxxxxx> 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. > > Signed-off-by: "Eric W. Biederman" <ebiederm@xxxxxxxxxxxx> Acked-by: Serge Hallyn <serge.hallyn@xxxxxxxxxxxxx> > --- > fs/namei.c | 25 +++++++++++++++++++++++++ > 1 files changed, 25 insertions(+), 0 deletions(-) > > diff --git a/fs/namei.c b/fs/namei.c > index 645268f23eb6..df7bd6e9c7b6 100644 > --- a/fs/namei.c > +++ b/fs/namei.c > @@ -3547,6 +3547,20 @@ void dentry_unhash(struct dentry *dentry) > spin_unlock(&dentry->d_lock); > } > > +static bool covered(struct vfsmount *mnt, struct dentry *dentry) > +{ > + /* test to see if a dentry is covered with a mount in > + * the current mount namespace. > + */ > + bool is_covered; > + > + rcu_read_lock(); > + is_covered = d_mountpoint(dentry) && __lookup_mnt(mnt, dentry, 1); > + rcu_read_unlock(); > + > + return is_covered; > +} > + > int vfs_rmdir(struct inode *dir, struct dentry *dentry) > { > int error = may_delete(dir, dentry, 1); > @@ -3622,6 +3636,9 @@ retry: > error = -ENOENT; > goto exit3; > } > + error = -EBUSY; > + if (covered(nd.path.mnt, dentry)) > + goto exit3; > error = security_path_rmdir(&nd.path, dentry); > if (error) > goto exit3; > @@ -3716,6 +3733,9 @@ retry: > inode = dentry->d_inode; > if (!inode) > goto slashes; > + error = -EBUSY; > + if (covered(nd.path.mnt, dentry)) > + goto exit2; > ihold(inode); > error = security_path_unlink(&nd.path, dentry); > if (error) > @@ -4164,6 +4184,11 @@ retry: > error = -ENOTEMPTY; > if (new_dentry == trap) > goto exit5; > + error = -EBUSY; > + if (covered(oldnd.path.mnt, old_dentry)) > + goto exit5; > + if (covered(newnd.path.mnt, new_dentry)) > + goto exit5; > > error = security_path_rename(&oldnd.path, old_dentry, > &newnd.path, new_dentry); > -- > 1.7.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html