svcrpc: modifying positive sunrpc cache entries is racy
diff mbox

Message ID 20101229204752.GC12218@fieldses.org
State RFC, archived
Headers show

Commit Message

Bruce Fields Dec. 29, 2010, 8:47 p.m. UTC
None

Patch
diff mbox

diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c
index a04ac91..70586ad 100644
--- a/net/sunrpc/svcauth_unix.c
+++ b/net/sunrpc/svcauth_unix.c
@@ -386,6 +386,21 @@  int auth_unix_forget_old(struct auth_domain *dom)
 }
 EXPORT_SYMBOL_GPL(auth_unix_forget_old);
 
+static void auth_unix_invalidate_ip_map(struct cache_detail *cd, struct ip_map *ipm)
+{
+	struct cache_head *ch;
+	struct ip_map ip;
+
+	ip.m_client = ipm->m_client;
+	ip.h.flags = CACHE_NEGATIVE;
+	ip.h.expiry_time = ipm->h.expiry_time;
+	ch = sunrpc_cache_update(cd, &ip.h, &ipm->h,
+				 hash_str(ipm->m_class, IP_HASHBITS) ^
+				 hash_ip6(ipm->m_addr));
+	if (ch)
+		cache_put(ch, cd);
+}
+
 struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
 {
 	struct ip_map *ipm;
@@ -401,8 +416,7 @@  struct auth_domain *auth_unix_lookup(struct net *net, struct in6_addr *addr)
 		return NULL;
 
 	if ((ipm->m_client->addr_changes - ipm->m_add_change) >0) {
-		if (test_and_set_bit(CACHE_NEGATIVE, &ipm->h.flags) == 0)
-			auth_domain_put(&ipm->m_client->h);
+		auth_unix_invalidate_ip_map(sn->ip_map_cache, ipm);
 		rv = NULL;
 	} else {
 		rv = &ipm->m_client->h;