From: Chuck Lever <cel@kernel.org>
To: Misbah Anjum N <misanjum@linux.ibm.com>,
Jeff Layton <jlayton@kernel.org>, NeilBrown <neil@brown.name>,
Olga Kornievskaia <okorniev@redhat.com>,
Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>, Simon Horman <horms@kernel.org>,
Yang Erkun <yangerkun@huawei.com>
Cc: linux-nfs@vger.kernel.org, linux-kernel@vger.kernel.org,
netdev@vger.kernel.org, Chuck Lever <chuck.lever@oracle.com>
Subject: [PATCH 3/6] SUNRPC: Defer ip_map sub-object cleanup past RCU grace period
Date: Fri, 01 May 2026 10:51:09 -0400 [thread overview]
Message-ID: <20260501-cache-uaf-fix-v1-3-a49928bf4817@oracle.com> (raw)
In-Reply-To: <20260501-cache-uaf-fix-v1-0-a49928bf4817@oracle.com>
From: Chuck Lever <chuck.lever@oracle.com>
ip_map_put() is already correct in that auth_domain_put() of
im->m_client reaches svcauth_unix_domain_release(), which defers
the actual kfree() of the unix_domain with call_rcu(); the ip_map
itself is freed via kfree_rcu(). Readers in c_show() under
cache_seq_start_rcu() therefore observe both objects until the
next RCU grace period.
This patch is a consistency change rather than a bug fix. The
svc_export and svc_expkey caches were converted to the
queue_rcu_work() pattern in commit 48db892356d6 ("NFSD: Defer
sub-object cleanup in export put callbacks") because path_put()
and auth_domain_put() must run in process context after the RCU
grace period. The next patch routes unix_gid through the same
mechanism. Sending ip_map through sunrpc_cache_queue_release()
unifies all four cache_detail .put callbacks on a single release
path and removes the implicit reliance on every current and
future auth_ops .domain_release implementation deferring its own
kfree() behind call_rcu().
Replace the rcu_head field with an rcu_work, move the kfree() and
auth_domain_put() into a new ip_map_release() taking a
work_struct, and have ip_map_put() invoke INIT_RCU_WORK() and
sunrpc_cache_queue_release() in place of kfree_rcu(). Switch
ip_map_cache_destroy() to sunrpc_cache_destroy_net() so
per-namespace teardown waits for outstanding release work
before freeing the cache_detail.
Assisted-by: Claude:claude-opus-4-7[1m]
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
net/sunrpc/svcauth_unix.c | 25 ++++++++++++++++---------
1 file changed, 16 insertions(+), 9 deletions(-)
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index 64a2658faddb..14688813c242 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -103,18 +103,26 @@ struct ip_map {
char m_class[8]; /* e.g. "nfsd" */
struct in6_addr m_addr;
struct unix_domain *m_client;
- struct rcu_head m_rcu;
+ struct rcu_work m_rwork;
};
+static void ip_map_release(struct work_struct *work)
+{
+ struct ip_map *im = container_of(to_rcu_work(work),
+ struct ip_map, m_rwork);
+
+ if (test_bit(CACHE_VALID, &im->h.flags) &&
+ !test_bit(CACHE_NEGATIVE, &im->h.flags))
+ auth_domain_put(&im->m_client->h);
+ kfree(im);
+}
+
static void ip_map_put(struct kref *kref)
{
- struct cache_head *item = container_of(kref, struct cache_head, ref);
- struct ip_map *im = container_of(item, struct ip_map,h);
+ struct ip_map *im = container_of(kref, struct ip_map, h.ref);
- if (test_bit(CACHE_VALID, &item->flags) &&
- !test_bit(CACHE_NEGATIVE, &item->flags))
- auth_domain_put(&im->m_client->h);
- kfree_rcu(im, m_rcu);
+ INIT_RCU_WORK(&im->m_rwork, ip_map_release);
+ sunrpc_cache_queue_release(&im->m_rwork);
}
static inline int hash_ip6(const struct in6_addr *ip)
@@ -1569,6 +1577,5 @@ void ip_map_cache_destroy(struct net *net)
sn->ip_map_cache = NULL;
cache_purge(cd);
- cache_unregister_net(cd, net);
- cache_destroy_net(cd, net);
+ sunrpc_cache_destroy_net(cd, net);
}
--
2.53.0
next prev parent reply other threads:[~2026-05-01 14:51 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 14:51 [PATCH 0/6] SUNRPC: Address remaining cache_check_rcu() UAF in cache content files Chuck Lever
2026-05-01 14:51 ` [PATCH 1/6] SUNRPC: Move cache_initialize() declaration to sunrpc-private header Chuck Lever
2026-05-01 14:51 ` [PATCH 2/6] SUNRPC: Provide a shared workqueue for cache release callbacks Chuck Lever
2026-05-01 14:51 ` Chuck Lever [this message]
2026-05-01 14:51 ` [PATCH 4/6] SUNRPC: Use shared release pattern for the unix_gid cache Chuck Lever
2026-05-01 14:51 ` [PATCH 5/6] SUNRPC: Hold cd->net for the lifetime of cache files Chuck Lever
2026-05-01 14:51 ` [PATCH 6/6] NFSD: Convert nfsd_export_shutdown() to sunrpc_cache_destroy_net() Chuck Lever
2026-05-05 5:32 ` [PATCH 0/6] SUNRPC: Address remaining cache_check_rcu() UAF in cache content files Jeff Layton
2026-05-05 10:49 ` Calum Mackay
2026-05-05 10:53 ` Chuck Lever
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260501-cache-uaf-fix-v1-3-a49928bf4817@oracle.com \
--to=cel@kernel.org \
--cc=Dai.Ngo@oracle.com \
--cc=anna@kernel.org \
--cc=chuck.lever@oracle.com \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=horms@kernel.org \
--cc=jlayton@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=misanjum@linux.ibm.com \
--cc=neil@brown.name \
--cc=netdev@vger.kernel.org \
--cc=okorniev@redhat.com \
--cc=pabeni@redhat.com \
--cc=tom@talpey.com \
--cc=trondmy@kernel.org \
--cc=yangerkun@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox