From e7c353b06d49a64e01150a8fed0726eece49ffe5 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 26 Feb 2020 11:59:02 -0500 Subject: [PATCH] follow_dotdot{,_rcu}(): lift LOOKUP_BENEATH checks out of loop Behaviour change: LOOKUP_BENEATH lookup of .. in absolute root yields an error even if it's not the process' root. That's possible only if you'd managed to escape chroot jail by way of procfs symlinks, but IMO the resulting behaviour is not worse - more consistent and easier to describe: ".." in root is "stay where you are", uness LOOKUP_BENEATH has been given, in which case it's "fail with EXDEV". Signed-off-by: Al Viro --- fs/namei.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 772d82daf3b46..577dc541a4d44 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1370,11 +1370,8 @@ static int follow_dotdot_rcu(struct nameidata *nd) unsigned seq; while (1) { - if (path_equal(&nd->path, &nd->root)) { - if (unlikely(nd->flags & LOOKUP_BENEATH)) - return -ECHILD; + if (path_equal(&nd->path, &nd->root)) break; - } if (nd->path.dentry != nd->path.mnt->mnt_root) { struct dentry *old = nd->path.dentry; @@ -1405,7 +1402,10 @@ static int follow_dotdot_rcu(struct nameidata *nd) nd->seq = seq; } } - if (likely(parent)) { + if (unlikely(!parent)) { + if (unlikely(nd->flags & LOOKUP_BENEATH)) + return -ECHILD; + } else { nd->path.dentry = parent; nd->seq = seq; } @@ -1447,11 +1447,8 @@ static int follow_dotdot(struct nameidata *nd) { struct dentry *parent = NULL; while (1) { - if (path_equal(&nd->path, &nd->root)) { - if (unlikely(nd->flags & LOOKUP_BENEATH)) - return -EXDEV; + if (path_equal(&nd->path, &nd->root)) break; - } if (nd->path.dentry != nd->path.mnt->mnt_root) { /* rare case of legitimate dget_parent()... */ parent = dget_parent(nd->path.dentry); @@ -1466,7 +1463,10 @@ static int follow_dotdot(struct nameidata *nd) if (unlikely(nd->flags & LOOKUP_NO_XDEV)) return -EXDEV; } - if (likely(parent)) { + if (unlikely(!parent)) { + if (unlikely(nd->flags & LOOKUP_BENEATH)) + return -EXDEV; + } else { dput(nd->path.dentry); nd->path.dentry = parent; } -- 2.39.5