tcp: use the echoed source route in cookie_v4_check()

When the ACK carries a source route option, cookie_v4_check() routes
the new socket to opt->faddr, where opt points to the options of the
received packet.

ip_options_compile() only fills faddr for options given by
setsockopt() (when called without an skb), so on receive faddr is 0
and the lookup is done for daddr 0, which gives a local route.

Use the options echoed by tcp_v4_save_options() instead, as
inet_csk_route_req() and inet_csk_route_child_sock() do with
ireq->ireq_opt. Read them after security_inet_conn_request(),
since CIPSO can replace ireq->ireq_opt there.

The route now goes to the first hop of the source route, so also
refuse a strict source route through a gateway, as
inet_csk_route_req() does.

Found by sashiko while reviewing the sk_mc_loop() fix.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Signed-off-by: Eric Dumazet <edumazet@kernel.org>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20261012101029.927296-3-edumazet@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Eric Dumazet 2026-10-12 12:10:29 +02:00 committed by Jakub Kicinski
parent 31b564f70d
commit 54d574d4af

View File

@ -404,12 +404,12 @@ static struct request_sock *cookie_tcp_check(struct net *net, struct sock *sk,
*/
struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
{
struct ip_options *opt = &TCP_SKB_CB(skb)->header.h4.opt;
const struct tcphdr *th = tcp_hdr(skb);
struct tcp_sock *tp = tcp_sk(sk);
struct inet_request_sock *ireq;
struct net *net = sock_net(sk);
struct tcp_request_sock *treq;
struct ip_options_rcu *opt;
struct request_sock *req;
struct sock *ret = sk;
struct flowi4 fl4;
@ -449,6 +449,8 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
SKB_DR_SET(reason, SECURITY_HOOK);
goto out_free;
}
/* Load ireq->ireq_opt after the LSM hook, which can replace it. */
opt = rcu_dereference_protected(ireq->ireq_opt, true);
tcp_ao_syncookie(sk, skb, req, AF_INET);
@ -461,7 +463,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
flowi4_init_output(&fl4, ireq->ir_iif, ireq->ir_mark,
ip_sock_rt_tos(sk), ip_sock_rt_scope(sk),
IPPROTO_TCP, inet_sk_flowi_flags(sk),
opt->srr ? opt->faddr : ireq->ir_rmt_addr,
(opt && opt->opt.srr) ? opt->opt.faddr : ireq->ir_rmt_addr,
ireq->ir_loc_addr, th->source, th->dest,
sk_uid(sk));
security_req_classify_flow(req, flowi4_to_flowi_common(&fl4));
@ -470,6 +472,12 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
SKB_DR_SET(reason, IP_OUTNOROUTES);
goto out_free;
}
/* Same check as in inet_csk_route_req(). */
if (opt && opt->opt.is_strictroute && rt->rt_uses_gateway) {
ip_rt_put(rt);
SKB_DR_SET(reason, IP_OUTNOROUTES);
goto out_free;
}
/* Try to redo what tcp_v4_send_synack did. */
req->rsk_window_clamp = READ_ONCE(tp->window_clamp) ? :