From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C846B3E3164 for ; Wed, 6 May 2026 08:24:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.53 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778055867; cv=none; b=GnlmypGd3rLebGnHXjYEjqZc9hGUKLPEZPT6czgtoTnUBAql233z6qL8n6J/sKcLZsVAILR8aXaQ+jeXRdr5AWzUqbjANTcSKR5Vvl8D9QyQmZm5lSZzbEk8uuqecPd00BYDT4ugD4ZtSFzAUhU8AazyVv3REi8Rc2XWr6BJanQ= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778055867; c=relaxed/simple; bh=/Fl6Eup1KJku7VmBbKrDm8Q65djqAuVDuYeegE3umw4=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=V1fL6Z7+oPAIBJUhoIlfsikuSc7zbR8YQnKoS1DNYdXNP+M84vbP71D5zTCKoJzXJsH51Jl51gPQFRRa26CIr1pOk9n9k+MiG54yQtEJobl/X6goSdojZuC83zXeMBO0u+124xgb2VnEhshL/925kdgHv3TKr/2bT6uNHN0D4rs= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=GbkuiFuT; arc=none smtp.client-ip=209.85.216.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="GbkuiFuT" Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-36520a83186so2690957a91.3 for ; Wed, 06 May 2026 01:24:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778055865; x=1778660665; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kaLjuq9Nze0HU4z8sneE7fCkabZfqnOhZ8tEew7UUs4=; b=GbkuiFuT7rd/q+q/a9Ckw4xtBrwtxlry9JRwTCPCtTK14g4pVYAPqbZUVy5MreOrbr w1f8Rw2+N+t/xK0NiikQ5dmO6VsUtrkgORxNv0HLSl9582BD4idkA50bHF/dCAEic3nd 7BDjCppxJEqLujHos6wAI4+4UeSmdVMopV3P/hmYXn2u7WvcdXTINa8eizVMqq28VoPQ vC/PpNdF2pf6pN8RWiEdV72UWTRj6VRTUzK7Mx4pYRclLjevLJKo6BjyuvMCCK0UaW1R vUM22iCtUvcozP6Oaymg9oW0EfiZUvFvIxX5YLqyPLcFtDjvddcc8AEdR+xdnA8Tbj3U 7qkg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778055865; x=1778660665; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=kaLjuq9Nze0HU4z8sneE7fCkabZfqnOhZ8tEew7UUs4=; b=Cxi8I5+/jzrIzX7p5e7n81osryEY2fpbjBLqr5ILVSCFdlvCOZRacPNiHmC2juf77Q xo1T6YZP+fytgyvLqhqu4BwEwyvNKeX+5E+KAfupjXLdf3vJEKugknnb35Eh8cc/Y1XS +Y9K64wAITjVhYii9IxTpTqGxNwVArmdsydr9ZFkUadSPCjTbdLVgihYrXRRfXOE7jZL lHU6ieAvDYLKh1SyIJoODfv3ZORm4BGITWghY7S4sVLSyKG3NbdoCIvUsPn4S1whas00 cZ/U4o11gcVSx2VuPgb6MCGLH0lDA7n1mfq6pW/jq3LIifRq2El61aLNQt7tMENStOel ZzhA== X-Forwarded-Encrypted: i=1; AFNElJ9BFKg9IndeGVUXPqtjITSMxsLQN6QqlZ/xo17nnpmLe/znnWLDvlzl2RKkPqAzal0g0nUaT/CUrrsh7wE=@vger.kernel.org X-Gm-Message-State: AOJu0YynIxOvsP171G3c1NFpVniZSgvKmr8j2lleJjo4lIfzl+jAhKD3 gqmjfRJfKau+UcXnTiB54U0NAftx8es60gmVMD0GNS80O5cgfYBNUe45IJuXhA== X-Gm-Gg: AeBDievjOcUOpZRqEMp4GXVyWDcTLP9hRnJyLmcSs+cmuWjSIFm3sdMm4oslad6xtW/ 8VzNB1eDZdOGQJTq0uc0DL7gkobJEiQXJgyxdJL6RySuqXPHU8aKzUIrW2iO0UvPpVqXWFw/bLT GD5aqPt1U6kQnx0rP0/9GfYPI9dOtqYNAzySpR/VHS90JvQU8TCVxYEpewvLMwDXH6hkfXrazQy N07IgnXfa6UBYRaoIvZrcrTuXZlr1ScF0EMt4Sam7gViNL3L1LGgSGAx6WDsc8hdGi/rdpKHN1V 3yPxU3e4wSxtug8cXVJoXVIcMTKgxJvKr+g0MTwMhmvR+nvfwia0fk0go0XVdPpiBSjO8meLflY RIldhbi9vUV0RKE54OwEP1YyZz9fvIgVZ/CcXu1JM4LDFsMJQBg1a+uYuXsDSNMveMPkwG+citA sf3ZSsKqNuBfL5UU30sfQ0SFAg6RLUcXPDrkj2NDswnqLysFg46JV7ff3kco0= X-Received: by 2002:a17:90b:5343:b0:35e:57cf:c0a3 with SMTP id 98e67ed59e1d1-365ac7808f4mr2213995a91.26.1778055864948; Wed, 06 May 2026 01:24:24 -0700 (PDT) Received: from csl-conti-dell7858.ntu.edu.sg ([155.69.195.57]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-365b12a1eddsm1000293a91.6.2026.05.06.01.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 01:24:24 -0700 (PDT) From: Maoyi Xie To: "David S . Miller" Cc: Jakub Kicinski , Paolo Abeni , Eric Dumazet , David Ahern , Alexey Kuznetsov , Willem de Bruijn , Willem de Bruijn , netdev@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Maoyi Xie Subject: [PATCH net v8 1/2] ipv6: flowlabel: take ip6_fl_lock across mem_check and fl_intern Date: Wed, 6 May 2026 16:24:15 +0800 Message-Id: <20260506082416.2259567-2-maoyixie.tju@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260506082416.2259567-1-maoyixie.tju@gmail.com> References: <20260506082416.2259567-1-maoyixie.tju@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Maoyi Xie mem_check() in net/ipv6/ip6_flowlabel.c reads fl_size without holding ip6_fl_lock. fl_intern() takes the lock immediately afterwards. The two checks therefore race against concurrent fl_intern, ip6_fl_gc and ip6_fl_purge writers, which makes the mem_check budget check approximate. Move spin_lock_bh(&ip6_fl_lock) and the matching unlock from fl_intern() into its only caller ipv6_flowlabel_get(). The mem_check() call now runs under the same critical section as the fl_intern() insert, so the budget check is exact. With all writers and the read of fl_size under ip6_fl_lock, convert fl_size from atomic_t to plain int. The four sites that update or read fl_size are fl_intern (insert path), ip6_fl_gc (garbage collector, the !sched check and the per-entry decrement), ip6_fl_purge (per-netns purge), and mem_check (budget check), and all four now run under ip6_fl_lock. This is a prerequisite for adding a per-netns budget alongside fl_size. The follow-up patch adds netns_ipv6::flowlabel_count and folds it into mem_check(). Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Suggested-by: Willem de Bruijn Reviewed-by: Willem de Bruijn Signed-off-by: Maoyi Xie --- net/ipv6/ip6_flowlabel.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index c92f98c6f..a89746431 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -40,7 +40,7 @@ #define FL_HASH_MASK 255 #define FL_HASH(l) (ntohl(l)&FL_HASH_MASK) -static atomic_t fl_size = ATOMIC_INIT(0); +static int fl_size; static struct ip6_flowlabel __rcu *fl_ht[FL_HASH_MASK+1]; static void ip6_fl_gc(struct timer_list *unused); @@ -163,7 +163,7 @@ static void ip6_fl_gc(struct timer_list *unused) if (time_after_eq(now, ttd)) { *flp = fl->next; fl_free(fl); - atomic_dec(&fl_size); + fl_size--; continue; } if (!sched || time_before(ttd, sched)) @@ -172,7 +172,7 @@ static void ip6_fl_gc(struct timer_list *unused) flp = &fl->next; } } - if (!sched && atomic_read(&fl_size)) + if (!sched && fl_size) sched = now + FL_MAX_LINGER; if (sched) { mod_timer(&ip6_fl_gc_timer, sched); @@ -196,7 +196,7 @@ static void __net_exit ip6_fl_purge(struct net *net) atomic_read(&fl->users) == 0) { *flp = fl->next; fl_free(fl); - atomic_dec(&fl_size); + fl_size--; continue; } flp = &fl->next; @@ -210,10 +210,10 @@ static struct ip6_flowlabel *fl_intern(struct net *net, { struct ip6_flowlabel *lfl; + lockdep_assert_held(&ip6_fl_lock); + fl->label = label & IPV6_FLOWLABEL_MASK; - rcu_read_lock(); - spin_lock_bh(&ip6_fl_lock); if (label == 0) { for (;;) { fl->label = htonl(get_random_u32())&IPV6_FLOWLABEL_MASK; @@ -235,8 +235,6 @@ static struct ip6_flowlabel *fl_intern(struct net *net, lfl = __fl_lookup(net, fl->label); if (lfl) { atomic_inc(&lfl->users); - spin_unlock_bh(&ip6_fl_lock); - rcu_read_unlock(); return lfl; } } @@ -244,9 +242,7 @@ static struct ip6_flowlabel *fl_intern(struct net *net, fl->lastuse = jiffies; fl->next = fl_ht[FL_HASH(fl->label)]; rcu_assign_pointer(fl_ht[FL_HASH(fl->label)], fl); - atomic_inc(&fl_size); - spin_unlock_bh(&ip6_fl_lock); - rcu_read_unlock(); + fl_size++; return NULL; } @@ -464,10 +460,14 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, static int mem_check(struct sock *sk) { - int room = FL_MAX_SIZE - atomic_read(&fl_size); + int room; struct ipv6_fl_socklist *sfl; int count = 0; + lockdep_assert_held(&ip6_fl_lock); + + room = FL_MAX_SIZE - fl_size; + if (room > FL_MAX_SIZE - FL_MAX_PER_SOCK) return 0; @@ -692,11 +692,19 @@ static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq, if (!sfl1) goto done; + rcu_read_lock(); + spin_lock_bh(&ip6_fl_lock); err = mem_check(sk); + if (err == 0) + fl1 = fl_intern(net, fl, freq->flr_label); + else + fl1 = NULL; + spin_unlock_bh(&ip6_fl_lock); + rcu_read_unlock(); + if (err != 0) goto done; - fl1 = fl_intern(net, fl, freq->flr_label); if (fl1) goto recheck; -- 2.34.1