Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'tcp-destroy-tcp-ao-tcp-md5-keys-in-sk_destruct'

Dmitry Safonov says:

====================
tcp: Destroy TCP-AO, TCP-MD5 keys in .sk_destruct()

On one side a minor/cosmetic issue, especially nowadays when
TCP-AO/TCP-MD5 signature verification failures aren't logged to dmesg.

Yet, I think worth addressing for two reasons:
- unsigned RST gets ignored by the peer and the connection is alive for
longer (keep-alive interval)
- netstat counters increase and trace events report that trusted BGP peer
is sending unsigned/incorrectly signed segments, which can ring alarm
on monitoring.
====================

Link: https://patch.msgid.link/20250909-b4-tcp-ao-md5-rst-finwait2-v5-0-9ffaaaf8b236@arista.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+45 -45
+4
include/net/tcp.h
··· 1941 1941 } 1942 1942 1943 1943 #define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key) 1944 + void tcp_md5_destruct_sock(struct sock *sk); 1944 1945 #else 1945 1946 static inline struct tcp_md5sig_key * 1946 1947 tcp_md5_do_lookup(const struct sock *sk, int l3index, ··· 1958 1957 } 1959 1958 1960 1959 #define tcp_twsk_md5_key(twsk) NULL 1960 + static inline void tcp_md5_destruct_sock(struct sock *sk) 1961 + { 1962 + } 1961 1963 #endif 1962 1964 1963 1965 int tcp_md5_alloc_sigpool(void);
-1
include/net/tcp_ao.h
··· 130 130 u32 snd_sne; 131 131 u32 rcv_sne; 132 132 refcount_t refcnt; /* Protects twsk destruction */ 133 - struct rcu_head rcu; 134 133 }; 135 134 136 135 #ifdef CONFIG_TCP_MD5SIG
+16
net/ipv4/tcp.c
··· 412 412 return rate64; 413 413 } 414 414 415 + #ifdef CONFIG_TCP_MD5SIG 416 + void tcp_md5_destruct_sock(struct sock *sk) 417 + { 418 + struct tcp_sock *tp = tcp_sk(sk); 419 + 420 + if (tp->md5sig_info) { 421 + 422 + tcp_clear_md5_list(sk); 423 + kfree(rcu_replace_pointer(tp->md5sig_info, NULL, 1)); 424 + static_branch_slow_dec_deferred(&tcp_md5_needed); 425 + tcp_md5_release_sigpool(); 426 + } 427 + } 428 + EXPORT_IPV6_MOD_GPL(tcp_md5_destruct_sock); 429 + #endif 430 + 415 431 /* Address-family independent initialization for a tcp_sock. 416 432 * 417 433 * NOTE: A lot of things set to zero explicitly by call to
+2 -3
net/ipv4/tcp_ao.c
··· 268 268 kfree_sensitive(key); 269 269 } 270 270 271 - static void tcp_ao_info_free_rcu(struct rcu_head *head) 271 + static void tcp_ao_info_free(struct tcp_ao_info *ao) 272 272 { 273 - struct tcp_ao_info *ao = container_of(head, struct tcp_ao_info, rcu); 274 273 struct tcp_ao_key *key; 275 274 struct hlist_node *n; 276 275 ··· 309 310 310 311 if (!twsk) 311 312 tcp_ao_sk_omem_free(sk, ao); 312 - call_rcu(&ao->rcu, tcp_ao_info_free_rcu); 313 + tcp_ao_info_free(ao); 313 314 } 314 315 315 316 void tcp_ao_time_wait(struct tcp_timewait_sock *tcptw, struct tcp_sock *tp)
+10 -27
net/ipv4/tcp_ipv4.c
··· 1503 1503 md5sig = rcu_dereference_protected(tp->md5sig_info, 1); 1504 1504 1505 1505 hlist_for_each_entry_safe(key, n, &md5sig->head, node) { 1506 - hlist_del_rcu(&key->node); 1506 + hlist_del(&key->node); 1507 1507 atomic_sub(sizeof(*key), &sk->sk_omem_alloc); 1508 - kfree_rcu(key, rcu); 1508 + kfree(key); 1509 1509 } 1510 1510 } 1511 1511 ··· 2494 2494 .ao_calc_key_sk = tcp_v4_ao_calc_key_sk, 2495 2495 #endif 2496 2496 }; 2497 + 2498 + static void tcp4_destruct_sock(struct sock *sk) 2499 + { 2500 + tcp_md5_destruct_sock(sk); 2501 + tcp_ao_destroy_sock(sk, false); 2502 + inet_sock_destruct(sk); 2503 + } 2497 2504 #endif 2498 2505 2499 2506 /* NOTE: A lot of things set to zero explicitly by call to ··· 2516 2509 2517 2510 #if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO) 2518 2511 tcp_sk(sk)->af_specific = &tcp_sock_ipv4_specific; 2512 + sk->sk_destruct = tcp4_destruct_sock; 2519 2513 #endif 2520 2514 2521 2515 return 0; 2522 2516 } 2523 - 2524 - #ifdef CONFIG_TCP_MD5SIG 2525 - static void tcp_md5sig_info_free_rcu(struct rcu_head *head) 2526 - { 2527 - struct tcp_md5sig_info *md5sig; 2528 - 2529 - md5sig = container_of(head, struct tcp_md5sig_info, rcu); 2530 - kfree(md5sig); 2531 - static_branch_slow_dec_deferred(&tcp_md5_needed); 2532 - tcp_md5_release_sigpool(); 2533 - } 2534 - #endif 2535 2517 2536 2518 static void tcp_release_user_frags(struct sock *sk) 2537 2519 { ··· 2557 2561 2558 2562 /* Cleans up our, hopefully empty, out_of_order_queue. */ 2559 2563 skb_rbtree_purge(&tp->out_of_order_queue); 2560 - 2561 - #ifdef CONFIG_TCP_MD5SIG 2562 - /* Clean up the MD5 key list, if any */ 2563 - if (tp->md5sig_info) { 2564 - struct tcp_md5sig_info *md5sig; 2565 - 2566 - md5sig = rcu_dereference_protected(tp->md5sig_info, 1); 2567 - tcp_clear_md5_list(sk); 2568 - call_rcu(&md5sig->rcu, tcp_md5sig_info_free_rcu); 2569 - rcu_assign_pointer(tp->md5sig_info, NULL); 2570 - } 2571 - #endif 2572 - tcp_ao_destroy_sock(sk, false); 2573 2564 2574 2565 /* Clean up a referenced TCP bind bucket. */ 2575 2566 if (inet_csk(sk)->icsk_bind_hash)
+5 -14
net/ipv4/tcp_minisocks.c
··· 377 377 } 378 378 EXPORT_SYMBOL(tcp_time_wait); 379 379 380 - #ifdef CONFIG_TCP_MD5SIG 381 - static void tcp_md5_twsk_free_rcu(struct rcu_head *head) 382 - { 383 - struct tcp_md5sig_key *key; 384 - 385 - key = container_of(head, struct tcp_md5sig_key, rcu); 386 - kfree(key); 387 - static_branch_slow_dec_deferred(&tcp_md5_needed); 388 - tcp_md5_release_sigpool(); 389 - } 390 - #endif 391 - 392 380 void tcp_twsk_destructor(struct sock *sk) 393 381 { 394 382 #ifdef CONFIG_TCP_MD5SIG 395 383 if (static_branch_unlikely(&tcp_md5_needed.key)) { 396 384 struct tcp_timewait_sock *twsk = tcp_twsk(sk); 397 385 398 - if (twsk->tw_md5_key) 399 - call_rcu(&twsk->tw_md5_key->rcu, tcp_md5_twsk_free_rcu); 386 + if (twsk->tw_md5_key) { 387 + kfree(twsk->tw_md5_key); 388 + static_branch_slow_dec_deferred(&tcp_md5_needed); 389 + tcp_md5_release_sigpool(); 390 + } 400 391 } 401 392 #endif 402 393 tcp_ao_destroy_sock(sk, true);
+8
net/ipv6/tcp_ipv6.c
··· 2110 2110 .ao_calc_key_sk = tcp_v4_ao_calc_key_sk, 2111 2111 #endif 2112 2112 }; 2113 + 2114 + static void tcp6_destruct_sock(struct sock *sk) 2115 + { 2116 + tcp_md5_destruct_sock(sk); 2117 + tcp_ao_destroy_sock(sk, false); 2118 + inet6_sock_destruct(sk); 2119 + } 2113 2120 #endif 2114 2121 2115 2122 /* NOTE: A lot of things set to zero explicitly by call to ··· 2132 2125 2133 2126 #if defined(CONFIG_TCP_MD5SIG) || defined(CONFIG_TCP_AO) 2134 2127 tcp_sk(sk)->af_specific = &tcp_sock_ipv6_specific; 2128 + sk->sk_destruct = tcp6_destruct_sock; 2135 2129 #endif 2136 2130 2137 2131 return 0;