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

net: tcp: allow tcp_timewait_sock to validate skbs before handing to device

Provide a callback to validate skb's originating from tcp timewait
socks before passing to the device layer. Full socks have a
sk_validate_xmit_skb member for checking that a device is capable of
performing offloads required for transmitting an skb. With psp, tcp
timewait socks will inherit the crypto state from their corresponding
full socks. Any ACKs or RSTs that originate from a tcp timewait sock
carrying psp state should be psp encapsulated.

Reviewed-by: Willem de Bruijn <willemb@google.com>
Signed-off-by: Daniel Zahka <daniel.zahka@gmail.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250917000954.859376-8-daniel.zahka@gmail.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Daniel Zahka and committed by
Paolo Abeni
0917bb13 8c511c1d

+20 -2
+5
include/net/inet_timewait_sock.h
··· 84 84 #if IS_ENABLED(CONFIG_INET_PSP) 85 85 struct psp_assoc __rcu *psp_assoc; 86 86 #endif 87 + #ifdef CONFIG_SOCK_VALIDATE_XMIT 88 + struct sk_buff* (*tw_validate_xmit_skb)(struct sock *sk, 89 + struct net_device *dev, 90 + struct sk_buff *skb); 91 + #endif 87 92 }; 88 93 #define tw_tclass tw_tos 89 94
+12 -2
net/core/dev.c
··· 3915 3915 struct net_device *dev) 3916 3916 { 3917 3917 #ifdef CONFIG_SOCK_VALIDATE_XMIT 3918 + struct sk_buff *(*sk_validate)(struct sock *sk, struct net_device *dev, 3919 + struct sk_buff *skb); 3918 3920 struct sock *sk = skb->sk; 3919 3921 3920 - if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) { 3921 - skb = sk->sk_validate_xmit_skb(sk, dev, skb); 3922 + sk_validate = NULL; 3923 + if (sk) { 3924 + if (sk_fullsock(sk)) 3925 + sk_validate = sk->sk_validate_xmit_skb; 3926 + else if (sk_is_inet(sk) && sk->sk_state == TCP_TIME_WAIT) 3927 + sk_validate = inet_twsk(sk)->tw_validate_xmit_skb; 3928 + } 3929 + 3930 + if (sk_validate) { 3931 + skb = sk_validate(sk, dev, skb); 3922 3932 } else if (unlikely(skb_is_decrypted(skb))) { 3923 3933 pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n"); 3924 3934 kfree_skb(skb);
+3
net/ipv4/inet_timewait_sock.c
··· 212 212 atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie)); 213 213 twsk_net_set(tw, sock_net(sk)); 214 214 timer_setup(&tw->tw_timer, tw_timer_handler, 0); 215 + #ifdef CONFIG_SOCK_VALIDATE_XMIT 216 + tw->tw_validate_xmit_skb = NULL; 217 + #endif 215 218 /* 216 219 * Because we use RCU lookups, we should not set tw_refcnt 217 220 * to a non null value before everything is setup for this