Messages in this thread Patch in this message | | | From | Kamal Mostafa <> | Subject | [PATCH 3.13.y-ckt 02/85] dcache: Handle escaped paths in prepend_path | Date | Tue, 20 Oct 2015 14:34:18 -0700 |
| |
3.13.11-ckt28 -stable review patch. If anyone has any objections, please let me know.
------------------
From: "Eric W. Biederman" <ebiederm@xmission.com>
commit cde93be45a8a90d8c264c776fab63487b5038a65 upstream.
A rename can result in a dentry that by walking up d_parent will never reach it's mnt_root. For lack of a better term I call this an escaped path.
prepend_path is called by four different functions __d_path, d_absolute_path, d_path, and getcwd.
__d_path only wants to see paths are connected to the root it passes in. So __d_path needs prepend_path to return an error.
d_absolute_path similarly wants to see paths that are connected to some root. Escaped paths are not connected to any mnt_root so d_absolute_path needs prepend_path to return an error greater than 1. So escaped paths will be treated like paths on lazily unmounted mounts.
getcwd needs to prepend "(unreachable)" so getcwd also needs prepend_path to return an error.
d_path is the interesting hold out. d_path just wants to print something, and does not care about the weird cases. Which raises the question what should be printed?
Given that <escaped_path>/<anything> should result in -ENOENT I believe it is desirable for escaped paths to be printed as empty paths. As there are not really any meaninful path components when considered from the perspective of a mount tree.
So tweak prepend_path to return an empty path with an new error code of 3 when it encounters an escaped path.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Kamal Mostafa <kamal@canonical.com> --- fs/dcache.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/fs/dcache.c b/fs/dcache.c index 09b4a3e..5769de8 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2903,6 +2903,13 @@ restart: if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { struct mount *parent = ACCESS_ONCE(mnt->mnt_parent); + /* Escaped? */ + if (dentry != vfsmnt->mnt_root) { + bptr = *buffer; + blen = *buflen; + error = 3; + break; + } /* Global root? */ if (mnt != parent) { dentry = ACCESS_ONCE(mnt->mnt_mountpoint); -- 1.9.1
| |