]> www.infradead.org Git - users/hch/misc.git/commitdiff
net: tcp: allow tcp_timewait_sock to validate skbs before handing to device
authorDaniel Zahka <daniel.zahka@gmail.com>
Wed, 17 Sep 2025 00:09:34 +0000 (17:09 -0700)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 18 Sep 2025 10:32:06 +0000 (12:32 +0200)
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>
include/net/inet_timewait_sock.h
net/core/dev.c
net/ipv4/inet_timewait_sock.c

index c1295246216c7fea23978faa402d580142b35a2e..3a31c74c9e15a2daa258dd2b794ef1415739de4d 100644 (file)
@@ -84,6 +84,11 @@ struct inet_timewait_sock {
 #if IS_ENABLED(CONFIG_INET_PSP)
        struct psp_assoc __rcu    *psp_assoc;
 #endif
+#ifdef CONFIG_SOCK_VALIDATE_XMIT
+       struct sk_buff*         (*tw_validate_xmit_skb)(struct sock *sk,
+                                                       struct net_device *dev,
+                                                       struct sk_buff *skb);
+#endif
 };
 #define tw_tclass tw_tos
 
index 384e59d7e715ee44d6eb16aabce6d343541d1cf4..5e22d062bac5faa1fadcb9ecf9da6f1cf74af961 100644 (file)
@@ -3915,10 +3915,20 @@ static struct sk_buff *sk_validate_xmit_skb(struct sk_buff *skb,
                                            struct net_device *dev)
 {
 #ifdef CONFIG_SOCK_VALIDATE_XMIT
+       struct sk_buff *(*sk_validate)(struct sock *sk, struct net_device *dev,
+                                      struct sk_buff *skb);
        struct sock *sk = skb->sk;
 
-       if (sk && sk_fullsock(sk) && sk->sk_validate_xmit_skb) {
-               skb = sk->sk_validate_xmit_skb(sk, dev, skb);
+       sk_validate = NULL;
+       if (sk) {
+               if (sk_fullsock(sk))
+                       sk_validate = sk->sk_validate_xmit_skb;
+               else if (sk_is_inet(sk) && sk->sk_state == TCP_TIME_WAIT)
+                       sk_validate = inet_twsk(sk)->tw_validate_xmit_skb;
+       }
+
+       if (sk_validate) {
+               skb = sk_validate(sk, dev, skb);
        } else if (unlikely(skb_is_decrypted(skb))) {
                pr_warn_ratelimited("unencrypted skb with no associated socket - dropping\n");
                kfree_skb(skb);
index 1f83f333b8ac49ab915de9d61ddf23a07f7780b3..2ca2912f61f47ecdc1a6105d9cb4b09b3444e540 100644 (file)
@@ -212,6 +212,9 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk,
                atomic64_set(&tw->tw_cookie, atomic64_read(&sk->sk_cookie));
                twsk_net_set(tw, sock_net(sk));
                timer_setup(&tw->tw_timer, tw_timer_handler, 0);
+#ifdef CONFIG_SOCK_VALIDATE_XMIT
+               tw->tw_validate_xmit_skb = NULL;
+#endif
                /*
                 * Because we use RCU lookups, we should not set tw_refcnt
                 * to a non null value before everything is setup for this