diff options
Diffstat (limited to 'vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch')
-rw-r--r-- | vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch | 110 |
1 files changed, 0 insertions, 110 deletions
diff --git a/vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch b/vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch deleted file mode 100644 index f9e7e6e61..000000000 --- a/vfs-Test-for-and-handle-paths-that-are-unreachable-f.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 14588dfe2e411056df5ba85ef88ad51730a2fa0a Mon Sep 17 00:00:00 2001 -From: "Eric W. Biederman" <ebiederm@xmission.com> -Date: Sat, 15 Aug 2015 20:27:13 -0500 -Subject: [PATCH 2/2] vfs: Test for and handle paths that are unreachable from - their mnt_root - -commit 397d425dc26da728396e66d392d5dcb8dac30c37 upstream. - -In rare cases a directory can be renamed out from under a bind mount. -In those cases without special handling it becomes possible to walk up -the directory tree to the root dentry of the filesystem and down -from the root dentry to every other file or directory on the filesystem. - -Like division by zero .. from an unconnected path can not be given -a useful semantic as there is no predicting at which path component -the code will realize it is unconnected. We certainly can not match -the current behavior as the current behavior is a security hole. - -Therefore when encounting .. when following an unconnected path -return -ENOENT. - -- Add a function path_connected to verify path->dentry is reachable - from path->mnt.mnt_root. AKA to validate that rename did not do - something nasty to the bind mount. - - To avoid races path_connected must be called after following a path - component to it's next path component. - -Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> -Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> ---- - fs/namei.c | 27 +++++++++++++++++++++++++-- - 1 file changed, 25 insertions(+), 2 deletions(-) - -diff --git a/fs/namei.c b/fs/namei.c -index 1c2105ed20c5..29b927938b8c 100644 ---- a/fs/namei.c -+++ b/fs/namei.c -@@ -560,6 +560,24 @@ static int __nd_alloc_stack(struct nameidata *nd) - return 0; - } - -+/** -+ * path_connected - Verify that a path->dentry is below path->mnt.mnt_root -+ * @path: nameidate to verify -+ * -+ * Rename can sometimes move a file or directory outside of a bind -+ * mount, path_connected allows those cases to be detected. -+ */ -+static bool path_connected(const struct path *path) -+{ -+ struct vfsmount *mnt = path->mnt; -+ -+ /* Only bind mounts can have disconnected paths */ -+ if (mnt->mnt_root == mnt->mnt_sb->s_root) -+ return true; -+ -+ return is_subdir(path->dentry, mnt->mnt_root); -+} -+ - static inline int nd_alloc_stack(struct nameidata *nd) - { - if (likely(nd->depth != EMBEDDED_LEVELS)) -@@ -1296,6 +1314,8 @@ static int follow_dotdot_rcu(struct nameidata *nd) - return -ECHILD; - nd->path.dentry = parent; - nd->seq = seq; -+ if (unlikely(!path_connected(&nd->path))) -+ return -ENOENT; - break; - } else { - struct mount *mnt = real_mount(nd->path.mnt); -@@ -1396,7 +1416,7 @@ static void follow_mount(struct path *path) - } - } - --static void follow_dotdot(struct nameidata *nd) -+static int follow_dotdot(struct nameidata *nd) - { - if (!nd->root.mnt) - set_root(nd); -@@ -1412,6 +1432,8 @@ static void follow_dotdot(struct nameidata *nd) - /* rare case of legitimate dget_parent()... */ - nd->path.dentry = dget_parent(nd->path.dentry); - dput(old); -+ if (unlikely(!path_connected(&nd->path))) -+ return -ENOENT; - break; - } - if (!follow_up(&nd->path)) -@@ -1419,6 +1441,7 @@ static void follow_dotdot(struct nameidata *nd) - } - follow_mount(&nd->path); - nd->inode = nd->path.dentry->d_inode; -+ return 0; - } - - /* -@@ -1634,7 +1657,7 @@ static inline int handle_dots(struct nameidata *nd, int type) - if (nd->flags & LOOKUP_RCU) { - return follow_dotdot_rcu(nd); - } else -- follow_dotdot(nd); -+ return follow_dotdot(nd); - } - return 0; - } --- -2.4.3 - |