Skip to content

Commit c8f7244

Browse files
edumazetkuba-moo
authored andcommitted
tcp: tcp_child_process() related UAF
tcp_child_process( .. child ...) currently calls sock_put(child). Unfortunately @child (named @nsk in callers) can be used after this point to send a RST packet. To fix this UAF, I remove the sock_put() from tcp_child_process() and let the callers handle this after it is safe. Remove @rsk variable in tcp_v4_do_rcv() and change tcp_v6_do_rcv() so that both functions look the same. Fixes: cfb6eeb ("[TCP]: MD5 Signature Option (RFC2385) support.") Reported-by: Damiano Melotti <melotti@google.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Link: https://patch.msgid.link/20260505153927.3435532-1-edumazet@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 770b136 commit c8f7244

3 files changed

Lines changed: 15 additions & 14 deletions

File tree

net/ipv4/tcp_ipv4.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1827,7 +1827,6 @@ INDIRECT_CALLABLE_DECLARE(struct dst_entry *ipv4_dst_check(struct dst_entry *,
18271827
int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
18281828
{
18291829
enum skb_drop_reason reason;
1830-
struct sock *rsk;
18311830

18321831
reason = psp_sk_rx_policy_check(sk, skb);
18331832
if (reason)
@@ -1863,24 +1862,21 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
18631862
return 0;
18641863
if (nsk != sk) {
18651864
reason = tcp_child_process(sk, nsk, skb);
1866-
if (reason) {
1867-
rsk = nsk;
1865+
sock_put(nsk);
1866+
if (reason)
18681867
goto reset;
1869-
}
18701868
return 0;
18711869
}
18721870
} else
18731871
sock_rps_save_rxhash(sk, skb);
18741872

18751873
reason = tcp_rcv_state_process(sk, skb);
1876-
if (reason) {
1877-
rsk = sk;
1874+
if (reason)
18781875
goto reset;
1879-
}
18801876
return 0;
18811877

18821878
reset:
1883-
tcp_v4_send_reset(rsk, skb, sk_rst_convert_drop_reason(reason));
1879+
tcp_v4_send_reset(sk, skb, sk_rst_convert_drop_reason(reason));
18841880
discard:
18851881
sk_skb_reason_drop(sk, skb, reason);
18861882
/* Be careful here. If this function gets more complicated and
@@ -2193,8 +2189,10 @@ int tcp_v4_rcv(struct sk_buff *skb)
21932189

21942190
rst_reason = sk_rst_convert_drop_reason(drop_reason);
21952191
tcp_v4_send_reset(nsk, skb, rst_reason);
2192+
sock_put(nsk);
21962193
goto discard_and_relse;
21972194
}
2195+
sock_put(nsk);
21982196
sock_put(sk);
21992197
return 0;
22002198
}

net/ipv4/tcp_minisocks.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,6 @@ enum skb_drop_reason tcp_child_process(struct sock *parent, struct sock *child,
10121012
}
10131013

10141014
bh_unlock_sock(child);
1015-
sock_put(child);
1015+
10161016
return reason;
10171017
}

net/ipv6/tcp_ipv6.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1617,12 +1617,13 @@ int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
16171617
if (sk->sk_state == TCP_LISTEN) {
16181618
struct sock *nsk = tcp_v6_cookie_check(sk, skb);
16191619

1620+
if (!nsk)
1621+
return 0;
16201622
if (nsk != sk) {
1621-
if (nsk) {
1622-
reason = tcp_child_process(sk, nsk, skb);
1623-
if (reason)
1624-
goto reset;
1625-
}
1623+
reason = tcp_child_process(sk, nsk, skb);
1624+
sock_put(nsk);
1625+
if (reason)
1626+
goto reset;
16261627
return 0;
16271628
}
16281629
} else
@@ -1827,8 +1828,10 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb)
18271828

18281829
rst_reason = sk_rst_convert_drop_reason(drop_reason);
18291830
tcp_v6_send_reset(nsk, skb, rst_reason);
1831+
sock_put(nsk);
18301832
goto discard_and_relse;
18311833
}
1834+
sock_put(nsk);
18321835
sock_put(sk);
18331836
return 0;
18341837
}

0 commit comments

Comments
 (0)