Message ID | 20220818170005.747015-20-dima@arista.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | net/tcp: Add TCP-AO support | expand |
On 8/18/22 19:59, Dmitry Safonov wrote: > Add Sequence Number Extension (SNE) extension for TCP-AO. > This is needed to protect long-living TCP-AO connections from replaying > attacks after sequence number roll-over, see RFC5925 (6.2). > +#ifdef CONFIG_TCP_AO > + ao = rcu_dereference_protected(tp->ao_info, > + lockdep_sock_is_held((struct sock *)tp)); > + if (ao) { > + if (ack < ao->snd_sne_seq) > + ao->snd_sne++; > + ao->snd_sne_seq = ack; > + } > +#endif > tp->snd_una = ack; > } ... snip ... > +#ifdef CONFIG_TCP_AO > + ao = rcu_dereference_protected(tp->ao_info, > + lockdep_sock_is_held((struct sock *)tp)); > + if (ao) { > + if (seq < ao->rcv_sne_seq) > + ao->rcv_sne++; > + ao->rcv_sne_seq = seq; > + } > +#endif > WRITE_ONCE(tp->rcv_nxt, seq); It should always be the case that (rcv_nxt == rcv_sne_seq) and (snd_una == snd_sne_seq) so the _sne_seq fields are redundant. It's possible to avoid those extra fields. However 8 bytes per TCP-AO socket is inconsequential. -- Regards, Leonard
On Tue, Aug 23, 2022 at 7:50 AM Leonard Crestez <cdleonard@gmail.com> wrote: > > On 8/18/22 19:59, Dmitry Safonov wrote: > > Add Sequence Number Extension (SNE) extension for TCP-AO. > > This is needed to protect long-living TCP-AO connections from replaying > > attacks after sequence number roll-over, see RFC5925 (6.2). > > > +#ifdef CONFIG_TCP_AO > > + ao = rcu_dereference_protected(tp->ao_info, > > + lockdep_sock_is_held((struct sock *)tp)); > > + if (ao) { > > + if (ack < ao->snd_sne_seq) > > + ao->snd_sne++; > > + ao->snd_sne_seq = ack; > > + } > > +#endif > > tp->snd_una = ack; > > } > > ... snip ... > > > +#ifdef CONFIG_TCP_AO > > + ao = rcu_dereference_protected(tp->ao_info, > > + lockdep_sock_is_held((struct sock *)tp)); > > + if (ao) { > > + if (seq < ao->rcv_sne_seq) > > + ao->rcv_sne++; > > + ao->rcv_sne_seq = seq; > > + } > > +#endif > > WRITE_ONCE(tp->rcv_nxt, seq); > > It should always be the case that (rcv_nxt == rcv_sne_seq) and (snd_una > == snd_sne_seq) so the _sne_seq fields are redundant. It's possible to > avoid those extra fields. There are cases where rcv_nxt and snd_una are set outside of tcp_rcv_nxt_update() and tcp_snd_una_update(), mostly during the initial handshake, so those cases would have to be taken care of explicitly, especially wrt rollovers. I see your point though, there may be a potential for some cleaning up here. Francesco
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index b8175ded8a70..8d326994d1a1 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3516,9 +3516,21 @@ static inline bool tcp_may_update_window(const struct tcp_sock *tp, static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) { u32 delta = ack - tp->snd_una; +#ifdef CONFIG_TCP_AO + struct tcp_ao_info *ao; +#endif sock_owned_by_me((struct sock *)tp); tp->bytes_acked += delta; +#ifdef CONFIG_TCP_AO + ao = rcu_dereference_protected(tp->ao_info, + lockdep_sock_is_held((struct sock *)tp)); + if (ao) { + if (ack < ao->snd_sne_seq) + ao->snd_sne++; + ao->snd_sne_seq = ack; + } +#endif tp->snd_una = ack; } @@ -3526,9 +3538,21 @@ static void tcp_snd_una_update(struct tcp_sock *tp, u32 ack) static void tcp_rcv_nxt_update(struct tcp_sock *tp, u32 seq) { u32 delta = seq - tp->rcv_nxt; +#ifdef CONFIG_TCP_AO + struct tcp_ao_info *ao; +#endif sock_owned_by_me((struct sock *)tp); tp->bytes_received += delta; +#ifdef CONFIG_TCP_AO + ao = rcu_dereference_protected(tp->ao_info, + lockdep_sock_is_held((struct sock *)tp)); + if (ao) { + if (seq < ao->rcv_sne_seq) + ao->rcv_sne++; + ao->rcv_sne_seq = seq; + } +#endif WRITE_ONCE(tp->rcv_nxt, seq); } @@ -6344,6 +6368,17 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, * simultaneous connect with crossed SYNs. * Particularly, it can be connect to self. */ +#ifdef CONFIG_TCP_AO + struct tcp_ao_info *ao; + + ao = rcu_dereference_protected(tp->ao_info, + lockdep_sock_is_held(sk)); + if (ao) { + ao->risn = th->seq; + ao->rcv_sne = 0; + ao->rcv_sne_seq = ntohl(th->seq); + } +#endif tcp_set_state(sk, TCP_SYN_RECV); if (tp->rx_opt.saw_tstamp) {