From eaf736aa7114d64e444cd381a4beb9abe2e05661 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 15 Feb 2021 12:03:23 -0500 Subject: [PATCH] UPSTREAM: fix handling of nd->depth on LOOKUP_CACHED failures in try_to_unlazy* [ Upstream commit eacd9aa8cedeb412842c7b339adbaa0477fdd5ad ] After switching to non-RCU mode, we want nd->depth to match the number of entries in nd->stack[] that need eventual path_put(). legitimize_links() takes care of that on failures; unfortunately, failure exits added for LOOKUP_CACHED do not. We could add the logics for that into those failure exits, both in try_to_unlazy() and in try_to_unlazy_next(), but since both checks are immediately followed by legitimize_links() and there's no calls of legitimize_links() other than those two... It's easier to move the check (and required handling of nd->depth on failure) into legitimize_links() itself. [caught by Jens: ... and since we are zeroing ->depth here, we need to do drop_links() first] Fixes: 6c6ec2b0a3e0 "fs: add support for LOOKUP_CACHED" Tested-by: Jens Axboe Change-Id: I6cf685bfce81acb4d68c3991b2a936968a39c739 Signed-off-by: Al Viro Signed-off-by: Greg Kroah-Hartman (cherry picked from commit 146fe79fff13fea7b5f3a9e913689e07fd4e6432) Bug: 268174392 Signed-off-by: Greg Kroah-Hartman --- fs/namei.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 414def462b99..d1e95cd6b28b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -633,6 +633,11 @@ static inline bool legitimize_path(struct nameidata *nd, static bool legitimize_links(struct nameidata *nd) { int i; + if (unlikely(nd->flags & LOOKUP_CACHED)) { + drop_links(nd); + nd->depth = 0; + return false; + } for (i = 0; i < nd->depth; i++) { struct saved *last = nd->stack + i; if (unlikely(!legitimize_path(nd, &last->link, last->seq))) { @@ -689,8 +694,6 @@ static bool try_to_unlazy(struct nameidata *nd) BUG_ON(!(nd->flags & LOOKUP_RCU)); nd->flags &= ~LOOKUP_RCU; - if (nd->flags & LOOKUP_CACHED) - goto out1; if (unlikely(!legitimize_links(nd))) goto out1; if (unlikely(!legitimize_path(nd, &nd->path, nd->seq))) @@ -727,8 +730,6 @@ static bool try_to_unlazy_next(struct nameidata *nd, struct dentry *dentry, unsi BUG_ON(!(nd->flags & LOOKUP_RCU)); nd->flags &= ~LOOKUP_RCU; - if (nd->flags & LOOKUP_CACHED) - goto out2; if (unlikely(!legitimize_links(nd))) goto out2; if (unlikely(!legitimize_mnt(nd->path.mnt, nd->m_seq)))