* [PATCH net] net: use the full socket in sk_mc_loop()
@ 2026-10-08 10:04 Theodor Arsenij Larionov Trichkine
2026-10-08 10:09 ` netdev-bot+sinfo
2026-10-08 11:23 ` Eric Dumazet
0 siblings, 2 replies; 5+ messages in thread
From: Theodor Arsenij Larionov Trichkine @ 2026-10-08 10:04 UTC (permalink / raw)
To: edumazet, kuniyu, pabeni, willemb, davem, kuba
Cc: horms, netdev, linux-kernel, Theodor Arsenij Larionov Trichkine
tcp_make_synack() sets skb->sk of a SYN-ACK to the request socket.
If the SYN-ACK destination is multicast, ip_mc_output() calls
sk_mc_loop() on it, and inet_test_bit(MC_LOOP, sk) reads inet_flags,
which is past the end of the smaller request_sock object.
KASAN reports a slab-out-of-bounds (or slab-use-after-free) read in
sk_mc_loop() from tcp_v4_send_synack() when a SYN with a multicast
source address reaches a listener.
Map the socket to the full socket before reading its flags.
Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
---
net/core/sock.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/core/sock.c b/net/core/sock.c
index e8551df8330f..1302c1e848b2 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -769,6 +769,7 @@ bool sk_mc_loop(const struct sock *sk)
{
if (dev_recursion_level())
return false;
+ sk = sk_const_to_full_sk(sk);
if (!sk)
return true;
/* IPV6_ADDRFORM can change sk->sk_family under us. */
base-commit: 6d25ffca055a77787c21a36b66c253f76239411b
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net: use the full socket in sk_mc_loop()
2026-10-08 10:04 [PATCH net] net: use the full socket in sk_mc_loop() Theodor Arsenij Larionov Trichkine
@ 2026-10-08 10:09 ` netdev-bot+sinfo
2026-10-08 11:23 ` Eric Dumazet
1 sibling, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-08 10:09 UTC (permalink / raw)
To: Theodor Arsenij Larionov Trichkine
Cc: edumazet, kuniyu, pabeni, willemb, davem, kuba, horms, netdev,
linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- How the issue was discovered, e.g. hit in production, hit during
development, syzbot report, manual code inspection, LLM or static
analysis tool scan.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net: use the full socket in sk_mc_loop()
2026-10-08 10:04 [PATCH net] net: use the full socket in sk_mc_loop() Theodor Arsenij Larionov Trichkine
2026-10-08 10:09 ` netdev-bot+sinfo
@ 2026-10-08 11:23 ` Eric Dumazet
2026-10-08 11:54 ` Theodor Arsenij Larionov-Trichkine
1 sibling, 1 reply; 5+ messages in thread
From: Eric Dumazet @ 2026-10-08 11:23 UTC (permalink / raw)
To: Theodor Arsenij Larionov Trichkine, Ido Schimmel
Cc: kuniyu, pabeni, willemb, davem, kuba, horms, netdev, linux-kernel
Le jeu. 8 oct. 2026 à 12:04, Theodor Arsenij Larionov Trichkine
<theodorlarionov@gmail.com> a écrit :
>
> tcp_make_synack() sets skb->sk of a SYN-ACK to the request socket.
> If the SYN-ACK destination is multicast, ip_mc_output() calls
> sk_mc_loop() on it, and inet_test_bit(MC_LOOP, sk) reads inet_flags,
> which is past the end of the smaller request_sock object.
>
> KASAN reports a slab-out-of-bounds (or slab-use-after-free) read in
> sk_mc_loop() from tcp_v4_send_synack() when a SYN with a multicast
> source address reaches a listener.
>
How does such a SYN reach a listener ?
ip_route_input_slow() rejects a multicast saddr as a martian source,
so this can not come from the wire.
I guess this needs a local sender : raw socket with IP_HDRINCL, and
the packet going through loopback, where the dst is kept
(skb_dst_force() in loopback_xmit()), so that ip_rcv_finish_core()
skips ip_route_input_noref().
Also the SYNACK route only uses ip_mc_output() if RTCF_LOCAL is set
and the output device is not loopback, so the SYN must target an
address of a non loopback device, and the source must be a group
joined on this device.
Please describe this in the changelog, and include the (trimmed)
KASAN splat, and a repro if you have one.
(Was it a public syzbot report ?)
> Map the socket to the full socket before reading its flags.
>
> Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
> Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
> ---
> net/core/sock.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/core/sock.c b/net/core/sock.c
> index e8551df8330f..1302c1e848b2 100644
> --- a/net/core/sock.c
> +++ b/net/core/sock.c
> @@ -769,6 +769,7 @@ bool sk_mc_loop(const struct sock *sk)
> {
> if (dev_recursion_level())
> return false;
> + sk = sk_const_to_full_sk(sk);
> if (!sk)
> return true;
> /* IPV6_ADDRFORM can change sk->sk_family under us. */
>
This only addresses the out-of-bounds read, masking the root cause.
We still answer a SYN with a multicast source. With this patch the
SYNACK is looped back depending on the listener MC_LOOP setting,
and syncookie SYNACK (skb->sk == NULL) were already sent.
tcp_v4_conn_request() only looks at the input route flags, ie the
destination of the SYN. tcp_v4_connect() refuses RTCF_MULTICAST and
RTCF_BROADCAST routes, I think we want the same check on the route
used for the SYNACK.
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6a30f11384547e6adaeff13a005c7ce1d316a602..aa928015cd143234d3d0c72e2b607d8347f73269
100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -779,6 +779,9 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
goto no_route;
if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
goto route_err;
+ /* Never send a SYNACK to a broadcast or multicast destination. */
+ if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
+ goto route_err;
rcu_read_unlock();
return &rt->dst;
pw-bot: cr
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net: use the full socket in sk_mc_loop()
2026-10-08 11:23 ` Eric Dumazet
@ 2026-10-08 11:54 ` Theodor Arsenij Larionov-Trichkine
2026-10-08 12:41 ` Eric Dumazet
0 siblings, 1 reply; 5+ messages in thread
From: Theodor Arsenij Larionov-Trichkine @ 2026-10-08 11:54 UTC (permalink / raw)
To: Eric Dumazet
Cc: Ido Schimmel, kuniyu, pabeni, willemb, davem, kuba, horms,
netdev, linux-kernel
> (Was it a public syzbot report ?)
No, this one is from a syzkaller-based fuzzer extended to target nftables.
The fuzzer reached it through an nft "dup" rule in prerouting, which
re-injects the SYN over loopback with its dst already attached, so the
martian check never sees the multicast source.
A raw IP_HDRINCL socket sending a SYN from 224.0.0.1 to an address on
a dummy device also reaches it, without nft. That is the repro in v2.
v2 with your inet_csk_route_req() check, the changelog, the trimmed
splat and the repro is here:
https://lore.kernel.org/netdev/20261008114942.1376889-1-theodorlarionov@gmail.com/
Thanks for the review,
Theodor
On Thu, Oct 8, 2026 at 2:23 PM Eric Dumazet <edumazet@kernel.org> wrote:
>
> Le jeu. 8 oct. 2026 à 12:04, Theodor Arsenij Larionov Trichkine
> <theodorlarionov@gmail.com> a écrit :
> >
> > tcp_make_synack() sets skb->sk of a SYN-ACK to the request socket.
> > If the SYN-ACK destination is multicast, ip_mc_output() calls
> > sk_mc_loop() on it, and inet_test_bit(MC_LOOP, sk) reads inet_flags,
> > which is past the end of the smaller request_sock object.
> >
> > KASAN reports a slab-out-of-bounds (or slab-use-after-free) read in
> > sk_mc_loop() from tcp_v4_send_synack() when a SYN with a multicast
> > source address reaches a listener.
> >
>
> How does such a SYN reach a listener ?
>
> ip_route_input_slow() rejects a multicast saddr as a martian source,
> so this can not come from the wire.
>
> I guess this needs a local sender : raw socket with IP_HDRINCL, and
> the packet going through loopback, where the dst is kept
> (skb_dst_force() in loopback_xmit()), so that ip_rcv_finish_core()
> skips ip_route_input_noref().
>
> Also the SYNACK route only uses ip_mc_output() if RTCF_LOCAL is set
> and the output device is not loopback, so the SYN must target an
> address of a non loopback device, and the source must be a group
> joined on this device.
>
> Please describe this in the changelog, and include the (trimmed)
> KASAN splat, and a repro if you have one.
>
> (Was it a public syzbot report ?)
>
> > Map the socket to the full socket before reading its flags.
> >
> > Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
> > Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
> > ---
> > net/core/sock.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/net/core/sock.c b/net/core/sock.c
> > index e8551df8330f..1302c1e848b2 100644
> > --- a/net/core/sock.c
> > +++ b/net/core/sock.c
> > @@ -769,6 +769,7 @@ bool sk_mc_loop(const struct sock *sk)
> > {
> > if (dev_recursion_level())
> > return false;
> > + sk = sk_const_to_full_sk(sk);
> > if (!sk)
> > return true;
> > /* IPV6_ADDRFORM can change sk->sk_family under us. */
> >
>
> This only addresses the out-of-bounds read, masking the root cause.
>
> We still answer a SYN with a multicast source. With this patch the
> SYNACK is looped back depending on the listener MC_LOOP setting,
> and syncookie SYNACK (skb->sk == NULL) were already sent.
>
> tcp_v4_conn_request() only looks at the input route flags, ie the
> destination of the SYN. tcp_v4_connect() refuses RTCF_MULTICAST and
> RTCF_BROADCAST routes, I think we want the same check on the route
> used for the SYNACK.
>
> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 6a30f11384547e6adaeff13a005c7ce1d316a602..aa928015cd143234d3d0c72e2b607d8347f73269
> 100644
> --- a/net/ipv4/inet_connection_sock.c
> +++ b/net/ipv4/inet_connection_sock.c
> @@ -779,6 +779,9 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
> goto no_route;
> if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway)
> goto route_err;
> + /* Never send a SYNACK to a broadcast or multicast destination. */
> + if (rt->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
> + goto route_err;
> rcu_read_unlock();
> return &rt->dst;
>
> pw-bot: cr
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net: use the full socket in sk_mc_loop()
2026-10-08 11:54 ` Theodor Arsenij Larionov-Trichkine
@ 2026-10-08 12:41 ` Eric Dumazet
0 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2026-10-08 12:41 UTC (permalink / raw)
To: Theodor Arsenij Larionov-Trichkine
Cc: Ido Schimmel, kuniyu, pabeni, willemb, davem, kuba, horms,
netdev, linux-kernel
Le jeu. 8 oct. 2026 à 13:54, Theodor Arsenij Larionov-Trichkine
<theodorlarionov@gmail.com> a écrit :
>
> > (Was it a public syzbot report ?)
>
> No, this one is from a syzkaller-based fuzzer extended to target nftables.
> The fuzzer reached it through an nft "dup" rule in prerouting, which
> re-injects the SYN over loopback with its dst already attached, so the
> martian check never sees the multicast source.
>
> A raw IP_HDRINCL socket sending a SYN from 224.0.0.1 to an address on
> a dummy device also reaches it, without nft. That is the repro in v2.
>
> v2 with your inet_csk_route_req() check, the changelog, the trimmed
> splat and the repro is here:
> https://lore.kernel.org/netdev/20261008114942.1376889-1-theodorlarionov@gmail.com/
>
> Thanks for the review,
> Theodor
OK, but given the current flood of patches, we ask for a ~24 hours
delay between each version.
Note that the Fixes: tag could have been refined a bit, no big deal.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-08 12:41 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-08 10:04 [PATCH net] net: use the full socket in sk_mc_loop() Theodor Arsenij Larionov Trichkine
2026-10-08 10:09 ` netdev-bot+sinfo
2026-10-08 11:23 ` Eric Dumazet
2026-10-08 11:54 ` Theodor Arsenij Larionov-Trichkine
2026-10-08 12:41 ` Eric Dumazet
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®