mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address
@ 2026-10-08 11:49 Theodor Arsenij Larionov Trichkine
  2026-10-08 11:56 ` netdev-bot+sinfo
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Theodor Arsenij Larionov Trichkine @ 2026-10-08 11:49 UTC (permalink / raw)
  To: edumazet, ncardwell, kuniyu, davem, kuba, pabeni
  Cc: horms, netdev, linux-kernel, Theodor Arsenij Larionov Trichkine

tcp_v4_conn_request() drops a SYN sent to a broadcast or multicast
address. The SYNACK route has no such check. A SYN with a multicast
source address can reach a listener when it is looped back with its
dst attached: ip_rcv_finish_core() then skips ip_route_input_noref()
and its martian source check. A raw IP_HDRINCL socket sending to a
local address does this, as does re-injection by nft dup or the
iptables TEE target.

If the SYN destination is an address on a non-loopback device and the
source is a group joined there (such as 224.0.0.1), the SYNACK route
has RTCF_MULTICAST and RTCF_LOCAL set, and ip_build_and_send_pkt()
sends it through ip_mc_output(). skb->sk of a SYNACK is the request
socket, so sk_mc_loop() reads inet_flags past the end of it:

BUG: KASAN: slab-out-of-bounds in sk_mc_loop+0x111/0x170
Read of size 8 at addr ffff88800f2b7f10 by task repro-raw/470
Call Trace:
 <IRQ>
 sk_mc_loop+0x111/0x170
 ip_mc_output+0x355/0x930
 ip_build_and_send_pkt+0xb87/0xc50
 tcp_v4_send_synack+0x500/0x6f0
 tcp_conn_request+0x2135/0x2d90
 tcp_v4_conn_request+0xa5/0x210
 tcp_rcv_state_process+0x136e/0x6920
 tcp_v4_do_rcv+0x339/0xb10
 tcp_v4_rcv+0x34ab/0x3ab0
 ip_protocol_deliver_rcu+0x6e/0x3e0
 ip_local_deliver_finish+0x34d/0x510
 ip_local_deliver+0x1bc/0x310
 ip_rcv+0x390/0x410
 __netif_receive_skb_one_core+0x199/0x1e0
 process_backlog+0x239/0x680
 __napi_poll+0xb5/0x650
 net_rx_action+0x980/0xd60
 handle_softirqs+0x17f/0x590
 do_softirq+0x3f/0x60
 </IRQ>
 <TASK>
 __local_bh_enable_ip+0x66/0x80
 __dev_queue_xmit+0xa65/0x3520
 ip_finish_output2+0xb00/0x16f0
 ip_output+0x2ad/0x4a0
 raw_sendmsg+0x245b/0x28e0
 inet_sendmsg+0x121/0x150
 __sys_sendto+0x450/0x4e0
 do_syscall_64+0xf6/0x500
 </TASK>

Allocated by task 470:
 inet_reqsk_alloc+0x97/0x6f0
 tcp_conn_request+0x4c6/0x2d90
 tcp_v4_conn_request+0xa5/0x210

The buggy address belongs to the object at ffff88800f2b7d60
 which belongs to the cache request_sock_TCP of size 312
The buggy address is located 120 bytes to the right of
 allocated 312-byte region [ffff88800f2b7d60, ffff88800f2b7e98)

Apply the same check to the SYNACK route in inet_csk_route_req().

Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
Suggested-by: Eric Dumazet <edumazet@kernel.org>
Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>
---
v2:
- Reject broadcast/multicast SYNACK routes in inet_csk_route_req() (Eric Dumazet).
- Describe how the SYN reaches the listener; add KASAN splat and repro.
v1: https://lore.kernel.org/netdev/20261008100423.1256884-1-theodorlarionov@gmail.com/

Reproducer (unprivileged, user + network namespace):

// gcc -O2 -static -o repro repro.c && ./repro
#define _GNU_SOURCE
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sched.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>

#define LOCAL_ADDR "10.0.0.1"	/* address of dummy0 */
#define MCAST_SRC  "224.0.0.1"	/* all-hosts, joined on every interface */
#define PORT       20000

static void die(const char *m) { perror(m); exit(1); }

static void wr(const char *path, const char *buf)
{
	int fd = open(path, O_WRONLY);

	if (fd < 0 || write(fd, buf, strlen(buf)) < 0)
		die(path);
	close(fd);
}

static void run(const char *cmd)
{
	if (system(cmd))
		fprintf(stderr, "failed: %s\n", cmd);
}

static uint16_t csum(const uint8_t *p, int len)
{
	uint32_t s = 0;
	int i;

	for (i = 0; i + 1 < len; i += 2)
		s += (p[i] << 8) | p[i + 1];
	if (i < len)
		s += p[i] << 8;
	while (s >> 16)
		s = (s & 0xffff) + (s >> 16);
	return ~s;
}

int main(void)
{
	char map[64];
	int uid = getuid(), gid = getgid();

	if (unshare(CLONE_NEWUSER | CLONE_NEWNET))
		die("unshare");
	wr("/proc/self/setgroups", "deny");
	snprintf(map, sizeof(map), "0 %d 1", uid);
	wr("/proc/self/uid_map", map);
	snprintf(map, sizeof(map), "0 %d 1", gid);
	wr("/proc/self/gid_map", map);

	run("ip link set lo up");
	run("ip link add dummy0 type dummy");
	run("ip addr add " LOCAL_ADDR "/24 dev dummy0");
	run("ip link set dummy0 up");

	int l = socket(AF_INET, SOCK_STREAM, 0);
	struct sockaddr_in a = {
		.sin_family = AF_INET,
		.sin_port = htons(PORT),
	};
	if (l < 0 || bind(l, (struct sockaddr *)&a, sizeof(a)) || listen(l, 128))
		die("listen");

	int raw = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
	if (raw < 0)
		die("raw socket");

	uint8_t pkt[40] = { 0 }, ph[32];
	uint32_t saddr = inet_addr(MCAST_SRC), daddr = inet_addr(LOCAL_ADDR);

	pkt[0] = 0x45;			/* IPv4, ihl 5 */
	pkt[3] = sizeof(pkt);		/* tot_len */
	pkt[8] = 64;			/* ttl */
	pkt[9] = IPPROTO_TCP;
	memcpy(pkt + 12, &saddr, 4);
	memcpy(pkt + 16, &daddr, 4);
	pkt[22] = PORT >> 8;		/* dport */
	pkt[23] = PORT & 0xff;
	pkt[32] = 5 << 4;		/* doff */
	pkt[33] = 0x02;			/* SYN */
	pkt[34] = 0x40;			/* window */

	for (int i = 0; i < 100; i++) {
		uint16_t c, sport = 10000 + i;
		struct sockaddr_in to = {
			.sin_family = AF_INET,
			.sin_addr.s_addr = daddr,
		};

		pkt[20] = sport >> 8;
		pkt[21] = sport & 0xff;
		pkt[36] = pkt[37] = 0;
		memcpy(ph, pkt + 12, 8);	/* pseudo header */
		ph[8] = 0;
		ph[9] = IPPROTO_TCP;
		ph[10] = 0;
		ph[11] = 20;
		memcpy(ph + 12, pkt + 20, 20);
		c = csum(ph, sizeof(ph));
		pkt[36] = c >> 8;
		pkt[37] = c & 0xff;
		if (sendto(raw, pkt, sizeof(pkt), 0, (struct sockaddr *)&to, sizeof(to)) < 0)
			die("sendto");
	}
	sleep(1);
	return 0;
}

 net/ipv4/inet_connection_sock.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6a30f1138454..aa928015cd14 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;
 

base-commit: 6d25ffca055a77787c21a36b66c253f76239411b
-- 
2.34.1


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

* Re: [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address
  2026-10-08 11:49 [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address Theodor Arsenij Larionov Trichkine
@ 2026-10-08 11:56 ` netdev-bot+sinfo
  2026-10-09  2:23 ` Jiayuan Chen
  2026-10-11 23:02 ` netdev-bot+sashiko
  2 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-08 11:56 UTC (permalink / raw)
  To: Theodor Arsenij Larionov Trichkine
  Cc: edumazet, ncardwell, kuniyu, davem, kuba, pabeni, 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 v2] tcp: do not send a SYNACK to a broadcast or multicast address
  2026-10-08 11:49 [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address Theodor Arsenij Larionov Trichkine
  2026-10-08 11:56 ` netdev-bot+sinfo
@ 2026-10-09  2:23 ` Jiayuan Chen
  2026-10-11 23:02 ` netdev-bot+sashiko
  2 siblings, 0 replies; 5+ messages in thread
From: Jiayuan Chen @ 2026-10-09  2:23 UTC (permalink / raw)
  To: Theodor Arsenij Larionov Trichkine, edumazet, ncardwell, kuniyu,
	davem, kuba, pabeni
  Cc: horms, netdev, linux-kernel


On 10/8/26 7:49 PM, Theodor Arsenij Larionov Trichkine wrote:
> tcp_v4_conn_request() drops a SYN sent to a broadcast or multicast
> address. The SYNACK route has no such check. A SYN with a multicast
> source address can reach a listener when it is looped back with its
> dst attached: ip_rcv_finish_core() then skips ip_route_input_noref()
> and its martian source check. A raw IP_HDRINCL socket sending to a
> local address does this, as does re-injection by nft dup or the
> iptables TEE target.
>
> If the SYN destination is an address on a non-loopback device and the
> source is a group joined there (such as 224.0.0.1), the SYNACK route
> has RTCF_MULTICAST and RTCF_LOCAL set, and ip_build_and_send_pkt()
> sends it through ip_mc_output(). skb->sk of a SYNACK is the request
> socket, so sk_mc_loop() reads inet_flags past the end of it:
>
> BUG: KASAN: slab-out-of-bounds in sk_mc_loop+0x111/0x170
> Read of size 8 at addr ffff88800f2b7f10 by task repro-raw/470
> Call Trace:
>   <IRQ>
>   sk_mc_loop+0x111/0x170
>   ip_mc_output+0x355/0x930
>   ip_build_and_send_pkt+0xb87/0xc50
>   tcp_v4_send_synack+0x500/0x6f0
>   tcp_conn_request+0x2135/0x2d90
>   tcp_v4_conn_request+0xa5/0x210
>   tcp_rcv_state_process+0x136e/0x6920
>   tcp_v4_do_rcv+0x339/0xb10
>   tcp_v4_rcv+0x34ab/0x3ab0
>   ip_protocol_deliver_rcu+0x6e/0x3e0
>   ip_local_deliver_finish+0x34d/0x510
>   ip_local_deliver+0x1bc/0x310
>   ip_rcv+0x390/0x410
>   __netif_receive_skb_one_core+0x199/0x1e0
>   process_backlog+0x239/0x680
>   __napi_poll+0xb5/0x650
>   net_rx_action+0x980/0xd60
>   handle_softirqs+0x17f/0x590
>   do_softirq+0x3f/0x60
>   </IRQ>
>   <TASK>
>   __local_bh_enable_ip+0x66/0x80
>   __dev_queue_xmit+0xa65/0x3520
>   ip_finish_output2+0xb00/0x16f0
>   ip_output+0x2ad/0x4a0
>   raw_sendmsg+0x245b/0x28e0
>   inet_sendmsg+0x121/0x150
>   __sys_sendto+0x450/0x4e0
>   do_syscall_64+0xf6/0x500
>   </TASK>
>
> Allocated by task 470:
>   inet_reqsk_alloc+0x97/0x6f0
>   tcp_conn_request+0x4c6/0x2d90
>   tcp_v4_conn_request+0xa5/0x210
>
> The buggy address belongs to the object at ffff88800f2b7d60
>   which belongs to the cache request_sock_TCP of size 312
> The buggy address is located 120 bytes to the right of
>   allocated 312-byte region [ffff88800f2b7d60, ffff88800f2b7e98)
>
> Apply the same check to the SYNACK route in inet_csk_route_req().
>
> Fixes: ca6fb0651883 ("tcp: attach SYNACK messages to request sockets instead of listener")
> Suggested-by: Eric Dumazet <edumazet@kernel.org>
> Signed-off-by: Theodor Arsenij Larionov Trichkine <theodorlarionov@gmail.com>


Reviewed-by: Jiayuan Chen <jiayuan.chen@linux.dev>


> ---
> v2:
> - Reject broadcast/multicast SYNACK routes in inet_csk_route_req() (Eric Dumazet).
> - Describe how the SYN reaches the listener; add KASAN splat and repro.
> v1: https://lore.kernel.org/netdev/20261008100423.1256884-1-theodorlarionov@gmail.com/


I think SYN with 192.x.x.255 as source can also tirgger this warning 
when rp_filter is disabled.


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

* Re: [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address
  2026-10-08 11:49 [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address Theodor Arsenij Larionov Trichkine
  2026-10-08 11:56 ` netdev-bot+sinfo
  2026-10-09  2:23 ` Jiayuan Chen
@ 2026-10-11 23:02 ` netdev-bot+sashiko
  2026-10-12  7:44   ` Eric Dumazet
  2 siblings, 1 reply; 5+ messages in thread
From: netdev-bot+sashiko @ 2026-10-11 23:02 UTC (permalink / raw)
  To: theodorlarionov
  Cc: edumazet, ncardwell, kuniyu, davem, kuba, pabeni, horms, netdev,
	linux-kernel

Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider.

Critical: 0 · High: 1 · Medium: 0 · Low: 0

If you believe none of the issues are legitimate, please reply to each
issue of Medium severity or higher and explain why the AI is wrong.
If any of them are legitimate and you plan to respin, please let patchwork
know by including "pw-bot: cr" as a separate line at the end of your reply
(one such reply per series is enough).

- [High] The fix is incomplete.

--

tcp: do not send a SYNACK to a broadcast or multicast address

This patch makes inet_csk_route_req() reject SYNACK routes that have
RTCF_BROADCAST or RTCF_MULTICAST set. A SYN with a multicast source that
is looped back with its dst attached skips the martian source check. Its
SYNACK then goes through ip_mc_output(), and sk_mc_loop() reads past the
end of the request socket.

> diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> index 6a30f11384547..aa928015cd143 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;

[Severity: High]
Does this cover the syncookie passive-open path? cookie_v4_check() in
net/ipv4/syncookies.c does its own route lookup to ireq->ir_rmt_addr.
The only check on the result is IS_ERR():

net/ipv4/syncookies.c:cookie_v4_check() {
    ...
	rt = ip_route_output_key(net, &fl4);
	if (IS_ERR(rt)) {
		SKB_DR_SET(reason, IP_OUTNOROUTES);
		goto out_free;
	}
    ...
	ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst);
    ...
}

In the syncookie case, tcp_v4_syn_recv_sock() uses that dst as is.
Neither inet_csk_route_req() nor inet_csk_route_child_sock() runs.

So it looks like a full child socket can still be created with
inet_daddr set to a multicast address such as 224.0.0.1. Active opens
already refuse this in tcp_v4_connect():

	if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
		ip_rt_put(rt);
		return -ENETUNREACH;

The ACK that completes the handshake can come in the way the commit
message describes for the SYN: raw IP_HDRINCL, nft dup or TEE, with
saddr=224.0.0.1. tcp_v4_cookie_check() passes any non-SYN segment to
cookie_v4_check().

The cookie can pass in two ways:

- cookie_tcp_check(), after a recent overflow. A netns owner can set
  tcp_syncookies=2 and send one unicast SYN. After that, ack_seq/seq can
  be brute forced at about 2^-29 per packet.
- cookie_bpf_check(), when a BPF program is in use.

Once that child is closed and in TIME_WAIT, a segment from the peer
would go down this path:

tcp_v4_rcv()
  tcp_v4_timewait_ack()
    tcp_v4_send_ack()
      ip_send_unicast_reply(ctl_sk, tw, ...)
        ip_route_output_flow()   /* daddr 224.0.0.1, no rt_flags check */
        skb_set_owner_edemux(nskb, tw)
        ip_push_pending_frames()
          ip_send_skb()
            ip_local_out(net, skb->sk, ...)
              ip_mc_output()
                sk_mc_loop(tw)

sk_mc_loop() does not check sk_fullsock():

	case AF_INET:
		return inet_test_bit(MC_LOOP, sk);

Wouldn't that read inet_flags past the end of the tcp_timewait_sock
object? That is the same out-of-bounds read this patch fixes for request
sockets. This path comes from reading the code at this commit; it has
not been reproduced.

Could the same rt_flags rejection (ip_rt_put() and drop) go after
ip_route_output_key() in cookie_v4_check()? For symmetry it could also
go in inet_csk_route_child_sock(). In practice that one only runs after
inet_csk_route_req() has passed, so it is just an inconsistency.

Another option would be to change sk_mc_loop() and
ip_send_unicast_reply() so they do not treat non-full sockets as
inet_sock.

>  	rcu_read_unlock();
>  	return &rt->dst;
>

-- 
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008114942.1376889-1-theodorlarionov%40gmail.com

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

* Re: [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address
  2026-10-11 23:02 ` netdev-bot+sashiko
@ 2026-10-12  7:44   ` Eric Dumazet
  0 siblings, 0 replies; 5+ messages in thread
From: Eric Dumazet @ 2026-10-12  7:44 UTC (permalink / raw)
  To: netdev-bot+sashiko
  Cc: theodorlarionov, ncardwell, kuniyu, davem, kuba, pabeni, horms,
	netdev, linux-kernel

Le lun. 12 oct. 2026 à 01:02, <netdev-bot+sashiko@kernel.org> a écrit :
>
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider.
>
> Critical: 0 · High: 1 · Medium: 0 · Low: 0
>
> If you believe none of the issues are legitimate, please reply to each
> issue of Medium severity or higher and explain why the AI is wrong.
> If any of them are legitimate and you plan to respin, please let patchwork
> know by including "pw-bot: cr" as a separate line at the end of your reply
> (one such reply per series is enough).
>
> - [High] The fix is incomplete.
>
> --
>
> tcp: do not send a SYNACK to a broadcast or multicast address
>
> This patch makes inet_csk_route_req() reject SYNACK routes that have
> RTCF_BROADCAST or RTCF_MULTICAST set. A SYN with a multicast source that
> is looped back with its dst attached skips the martian source check. Its
> SYNACK then goes through ip_mc_output(), and sk_mc_loop() reads past the
> end of the request socket.
>
> > diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
> > index 6a30f11384547..aa928015cd143 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;
>
> [Severity: High]
> Does this cover the syncookie passive-open path? cookie_v4_check() in
> net/ipv4/syncookies.c does its own route lookup to ireq->ir_rmt_addr.
> The only check on the result is IS_ERR():
>
> net/ipv4/syncookies.c:cookie_v4_check() {
>     ...
>         rt = ip_route_output_key(net, &fl4);
>         if (IS_ERR(rt)) {
>                 SKB_DR_SET(reason, IP_OUTNOROUTES);
>                 goto out_free;
>         }
>     ...
>         ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst);
>     ...
> }
>
> In the syncookie case, tcp_v4_syn_recv_sock() uses that dst as is.
> Neither inet_csk_route_req() nor inet_csk_route_child_sock() runs.
>
> So it looks like a full child socket can still be created with
> inet_daddr set to a multicast address such as 224.0.0.1. Active opens
> already refuse this in tcp_v4_connect():
>
>         if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
>                 ip_rt_put(rt);
>                 return -ENETUNREACH;
>
> The ACK that completes the handshake can come in the way the commit
> message describes for the SYN: raw IP_HDRINCL, nft dup or TEE, with
> saddr=224.0.0.1. tcp_v4_cookie_check() passes any non-SYN segment to
> cookie_v4_check().
>
> The cookie can pass in two ways:
>
> - cookie_tcp_check(), after a recent overflow. A netns owner can set
>   tcp_syncookies=2 and send one unicast SYN. After that, ack_seq/seq can
>   be brute forced at about 2^-29 per packet.
> - cookie_bpf_check(), when a BPF program is in use.
>
> Once that child is closed and in TIME_WAIT, a segment from the peer
> would go down this path:
>
> tcp_v4_rcv()
>   tcp_v4_timewait_ack()
>     tcp_v4_send_ack()
>       ip_send_unicast_reply(ctl_sk, tw, ...)
>         ip_route_output_flow()   /* daddr 224.0.0.1, no rt_flags check */
>         skb_set_owner_edemux(nskb, tw)
>         ip_push_pending_frames()
>           ip_send_skb()
>             ip_local_out(net, skb->sk, ...)
>               ip_mc_output()
>                 sk_mc_loop(tw)
>
> sk_mc_loop() does not check sk_fullsock():
>
>         case AF_INET:
>                 return inet_test_bit(MC_LOOP, sk);
>
> Wouldn't that read inet_flags past the end of the tcp_timewait_sock
> object? That is the same out-of-bounds read this patch fixes for request
> sockets. This path comes from reading the code at this commit; it has
> not been reproduced.
>
> Could the same rt_flags rejection (ip_rt_put() and drop) go after
> ip_route_output_key() in cookie_v4_check()? For symmetry it could also
> go in inet_csk_route_child_sock(). In practice that one only runs after
> inet_csk_route_req() has passed, so it is just an inconsistency.
>
> Another option would be to change sk_mc_loop() and
> ip_send_unicast_reply() so they do not treat non-full sockets as
> inet_sock.
>
> >       rcu_read_unlock();
> >       return &rt->dst;
> >
>
> --
> Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261008114942.1376889-1-theodorlarionov%40gmail.com

OK, it turns out we have not one, but three different bugs.

I am working on a series of three patches. I am preparing for it.

1/3 tcp: do not send a SYNACK to a broadcast or multicast address
2/3 ipv4: do not send a TCP reply to a broadcast or multicast address
3/3 tcp: use the saved source route in cookie_v4_check()

pw-bot: cr

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

end of thread, other threads:[~2026-10-12  7:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-08 11:49 [PATCH net v2] tcp: do not send a SYNACK to a broadcast or multicast address Theodor Arsenij Larionov Trichkine
2026-10-08 11:56 ` netdev-bot+sinfo
2026-10-09  2:23 ` Jiayuan Chen
2026-10-11 23:02 ` netdev-bot+sashiko
2026-10-12  7:44   ` 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®