Commit 0917bb13 authored by Daniel Zahka's avatar Daniel Zahka Committed by Paolo Abeni
Browse files

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: default avatarWillem de Bruijn <willemb@google.com>
Signed-off-by: default avatarDaniel Zahka <daniel.zahka@gmail.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Link: https://patch.msgid.link/20250917000954.859376-8-daniel.zahka@gmail.com


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 8c511c1d
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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

+12 −2
Original line number Diff line number Diff line
@@ -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);
+3 −0
Original line number Diff line number Diff line
@@ -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