mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v2 1/2] ipv6: fix cached route reuse for SO_MARK control messages
@ 2026-11-04  9:22 Xia Yan
  2026-11-04  9:22 ` [PATCH net v2 2/2] selftests: net: exercise SO_MARK on connected sockets Xia Yan
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Xia Yan @ 2026-11-04  9:22 UTC (permalink / raw)
  To: netdev
  Cc: dsahern, idosch, davem, edumazet, kuba, pabeni, horms,
	willemdebruijn.kernel, linux-kernel, stable, yana06070, shuah,
	linux-kselftest, willemb

A connected IPv6 UDP or ping socket can reuse a route selected for the
socket mark when an SO_MARK control message supplies a different mark. A
packet can then bypass a prohibit rule for its per-message mark instead
of failing with EACCES.

ip6_sk_dst_lookup_flow() consults the socket dst cache even when
connected is false. That argument only controls whether a new route is
cached. The cache check does not compare the mark used for the lookup.

Record whether SO_MARK was supplied by the control messages, including
an explicit zero. For UDP and ping sends with that flag, call
ip6_dst_lookup_flow() directly. Keep the cache handling for sends
without SO_MARK unchanged.

The concurrent SO_MARK case was identified in the review of v1.

The issue was reproduced on UML with connected sockets and mark-based
routing. A separate test kernel paused the sender after it acquired a
cached dst reference; another thread then changed the socket mark to the
per-message mark. The old code still sent the packet. The fix bypasses
that cache path and returns EACCES. The 50 UDP/ping route checks and all
54 cmsg_so_mark.sh cases pass with the fix.

Fixes: c6af0c227a22 ("ip: support SO_MARK cmsg")
Cc: stable@vger.kernel.org
Signed-off-by: Xia Yan <yanxia@cmss.chinamobile.com>
---
v2:
  - Replace the current sk_mark comparison with a flag recording whether
    SO_MARK was supplied, and bypass the cache for those UDP/ping sends.
  - Add connected-socket regression coverage in patch 2.

v1: https://lore.kernel.org/netdev/20261030141435.779302-1-yanxia@cmss.chinamobile.com/T/
Review: https://lore.kernel.org/netdev/179371875338.488856.4546363285391899557@kernel.org/

Tested on net cb284914e749388eef402938bdb3115fe1f6d337 with GCC 12.3.1:
  - UML normal: baseline 41/50, v1 and v2 50/50; the same extended
    cmsg_so_mark.sh has 2/54 failures on baseline and passes on v1/v2.
  - Test-only pause: baseline/v1 retain the old cached dst and send after
    the socket mark changes; v2 skips the cache helper and gets EACCES.
  - x86_64 W=1: full vmlinux, bzImage and modules builds pass on baseline
    and v2 using configs derived from allmodconfig and allyesconfig.
    WERROR, KASAN and KCSAN are disabled; KUNIT_ALL_TESTS is also disabled
    for allyesconfig. The unmodified configs fail on the same existing
    GCC 12.3.1 Werror diagnostics on both sides. Derived-build diagnostics
    are identical on both sides, including their occurrence counts.


 include/net/ipv6.h  | 1 +
 net/ipv6/datagram.c | 2 ++
 net/ipv6/ping.c     | 5 ++++-
 net/ipv6/udp.c      | 5 ++++-
 4 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/include/net/ipv6.h b/include/net/ipv6.h
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -353,6 +353,7 @@
 	__s16 tclass;
 	__u16 gso_size;
 	__s8  dontfrag;
+	bool mark_set;
 	struct ipv6_txoptions *opt;
 };
 
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c
--- a/net/ipv6/datagram.c
+++ b/net/ipv6/datagram.c
@@ -819,6 +819,8 @@
 			err = __sock_cmsg_send(sk, cmsg, &ipc6->sockc);
 			if (err)
 				return err;
+			if (cmsg->cmsg_type == SO_MARK)
+				ipc6->mark_set = true;
 			continue;
 		}
 
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -1693,7 +1693,10 @@
 
 	fl6->flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6->flowlabel);
 
-	dst = ip6_sk_dst_lookup_flow(sk, fl6, final_p, connected);
+	if (ipc6.mark_set)
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, fl6, final_p);
+	else
+		dst = ip6_sk_dst_lookup_flow(sk, fl6, final_p, connected);
 	if (IS_ERR(dst)) {
 		err = PTR_ERR(dst);
 		dst = NULL;
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -148,7 +148,10 @@
 
 	fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
 
-	dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, false);
+	if (ipc6.mark_set)
+		dst = ip6_dst_lookup_flow(sock_net(sk), sk, &fl6, daddr);
+	else
+		dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, false);
 	if (IS_ERR(dst))
 		return PTR_ERR(dst);
 	rt = dst_rt6_info(dst);



^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-11-05  9:39 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04  9:22 [PATCH net v2 1/2] ipv6: fix cached route reuse for SO_MARK control messages Xia Yan
2026-11-04  9:22 ` [PATCH net v2 2/2] selftests: net: exercise SO_MARK on connected sockets Xia Yan
2026-11-04  9:23   ` Xia Yan
2026-11-05  9:39   ` netdev-bot+sashiko
2026-11-04  9:23 ` [PATCH net v2 1/2] ipv6: fix cached route reuse for SO_MARK control messages Xia Yan
2026-11-04  9:29 ` netdev-bot+sinfo
2026-11-04  9:50   ` Xia Yan
2026-11-05  9:38 ` netdev-bot+sashiko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®