Thread (3 messages) flat view 3 messages, 2 authors, 1d ago
WARM1d

[PATCH net 1/1] ipv6: flowlabel: enforce the per-socket lease cap on reused labels

From: Zhiling Zou <hidden>
Date: 2026-08-03 11:22:26
Subsystem: networking [general], networking [ipv4/ipv6], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, David Ahern, Ido Schimmel, Linus Torvalds

ipv6_flowlabel_get() lets a socket reacquire an existing flowlabel and
link another ipv6_fl_socklist entry through the recheck path.

mem_check() only counts socket leases after fl_size falls below
FL_MAX_SIZE - FL_MAX_PER_SOCK. Reusing an existing flowlabel does not
increase fl_size, so duplicate GET requests can keep taking the
recheck path and grow one socket's lease list without ever hitting the
FL_MAX_PER_SOCK limit.

Check the current socket lease count before linking a reused
flowlabel. This keeps the duplicate-acquisition path consistent with
the long-standing per-socket cap without changing the global budget
logic for new flowlabels.

Fixes: 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <redacted>
Signed-off-by: Zhiling Zou <redacted>
---
 net/ipv6/ip6_flowlabel.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1ab5ad0dcf24f..e295f85bcc604 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -493,6 +493,24 @@ static int mem_check(struct sock *sk)
 	return 0;
 }
 
+static int mem_check_dup(struct sock *sk)
+{
+	struct ipv6_fl_socklist *sfl;
+	int count = 0;
+
+	lockdep_assert_held(&ip6_fl_lock);
+
+	rcu_read_lock();
+	for_each_sk_fl_rcu(sk, sfl)
+		count++;
+	rcu_read_unlock();
+
+	if (count >= FL_MAX_PER_SOCK && !capable(CAP_NET_ADMIN))
+		return -ENOBUFS;
+
+	return 0;
+}
+
 static inline void fl_link(struct sock *sk, struct ipv6_fl_socklist *sfl,
 			   struct ip6_flowlabel *fl)
 {
@@ -679,10 +697,17 @@ static int ipv6_flowlabel_get(struct sock *sk, struct in6_flowlabel_req *freq,
 			err = -ENOMEM;
 			if (!sfl1)
 				goto release;
-			if (fl->linger > fl1->linger)
-				fl1->linger = fl->linger;
-			if ((long)(fl->expires - fl1->expires) > 0)
-				fl1->expires = fl->expires;
+			spin_lock_bh(&ip6_fl_lock);
+			err = mem_check_dup(sk);
+			if (err == 0) {
+				if (fl->linger > fl1->linger)
+					fl1->linger = fl->linger;
+				if ((long)(fl->expires - fl1->expires) > 0)
+					fl1->expires = fl->expires;
+			}
+			spin_unlock_bh(&ip6_fl_lock);
+			if (err != 0)
+				goto release;
 			fl_link(sk, sfl1, fl1);
 			fl_free(fl);
 			return 0;
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help