Thread (28 messages) 28 messages, 2 authors, 2023-09-12

Re: [PATCH v11 net-next 06/23] net/tcp: Add TCP-AO sign to outgoing packets

From: Dmitry Safonov <hidden>
Date: 2023-09-12 20:19:54
Also in: lkml

On 9/12/23 17:47, Eric Dumazet wrote:
On Mon, Sep 11, 2023 at 11:04 PM Dmitry Safonov [off-list ref] wrote:
[..]
quoted
@@ -1378,6 +1430,34 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb,
                                               md5, sk, skb);
        }
 #endif
+#ifdef CONFIG_TCP_AO
+       if (ao) {
+               u8 *traffic_key;
+               void *tkey_buf = NULL;
+               __be32 disn;
+
+               sk_gso_disable(sk);
Why is this needed here in a fast path ? This should happen once.

It seems you copied MD5 old logic, I think we should do better.
Yeah, I think it survived from TCP-AO PoC where it was mostly TCP-MD5
copy'n'paste. And survived by the reason that it it's small and seems
yet done for TCP-MD5.

Which doesn't mean it can't be better. The MD5 code seems to have been
introduced in:
https://marc.info/?l=linux-netdev&m=121445989106145&w=2

Currently, the described child sk issue can't happen as tcp_md5sig_info
is allocated in tcp_md5sig_info_add() regardless if it is setsockopt()
or child socket allocation. And tcp_md5sig_info_add() does
sk_gso_disable(sk).

I presume, sk_gso_disable() can be removed from both TCP-AO/TCP-MD5.
The only exception will be twsk, where it doesn't seem to matter.
quoted
+               if (unlikely(tcb->tcp_flags & TCPHDR_SYN)) {
+                       if (tcb->tcp_flags & TCPHDR_ACK)
+                               disn = ao->risn;
+                       else
+                               disn = 0;
+
+                       tkey_buf = kmalloc(tcp_ao_digest_size(ao_key), GFP_ATOMIC);
+                       if (!tkey_buf)
+                               return -ENOMEM;
This leaks an skb.
Ouch! Thanks for noticing, will repair.
quoted
+                       traffic_key = tkey_buf;
+                       tp->af_specific->ao_calc_key_sk(ao_key, traffic_key,
+                                                       sk, ao->lisn, disn, true);
+               } else {
+                       traffic_key = snd_other_key(ao_key);
+               }
+               tp->af_specific->calc_ao_hash(opts.hash_location, ao_key, sk, skb,
+                                             traffic_key,
+                                             opts.hash_location - (u8 *)th, 0);
+               kfree(tkey_buf);
+       }
+#endif

        /* BPF prog is the last one writing header option */
        bpf_skops_write_hdr_opt(sk, skb, NULL, NULL, 0, &opts);
[..]
quoted
@@ -1837,8 +1921,17 @@ unsigned int tcp_current_mss(struct sock *sk)
                if (mtu != inet_csk(sk)->icsk_pmtu_cookie)
                        mss_now = tcp_sync_mss(sk, mtu);
        }
-
-       header_len = tcp_established_options(sk, NULL, &opts, &md5) +
+#ifdef CONFIG_TCP_AO
+       ao_info = rcu_dereference_check(tp->ao_info, lockdep_sock_is_held(sk));
+       if (ao_info)
+               /* TODO: verify if we can access current_key or we need to pass
+                * it from every caller of tcp_current_mss instead. The reason
+                * is that the current_key pointer can change asynchronously
+                * from the rx path.
+                */
+               ao_key = READ_ONCE(ao_info->current_key);
+#endif
+       header_len = tcp_established_options(sk, NULL, &opts, &md5, ao_key) +
                     sizeof(struct tcphdr);
Adding yet another argument in TCP fast path routines is very unfortunate...

Could we merge md5/ao_key, and have a field giving the type ?
Hmm, I'll try to refactor this a little.

Thanks for taking a look,
          Dmitry
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help