diff mbox series

[19/31] net/tcp: Add TCP-AO SNE support

Message ID 20220818170005.747015-20-dima@arista.com
State Superseded
Headers show
Series net/tcp: Add TCP-AO support | expand

Commit Message

Dmitry Safonov Aug. 18, 2022, 4:59 p.m. UTC
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).

Co-developed-by: Francesco Ruggeri <fruggeri@arista.com>
Signed-off-by: Francesco Ruggeri <fruggeri@arista.com>
Co-developed-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Salam Noureddine <noureddine@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
---
 net/ipv4/tcp_input.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

Comments

Leonard Crestez Aug. 23, 2022, 2:50 p.m. UTC | #1
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
Francesco Ruggeri Aug. 23, 2022, 10:40 p.m. UTC | #2
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 mbox series

Patch

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) {