diff options
| author | Dmitry Safonov <dima@arista.com> | 2023-12-04 19:00:41 +0000 | 
|---|---|---|
| committer | Paolo Abeni <pabeni@redhat.com> | 2023-12-06 12:36:55 +0100 | 
| commit | da7dfaa6d6f731c30eca6ffa808b83634d43e26f (patch) | |
| tree | 6664d5827e0611238fc46e4225a8b435754d72a7 | |
| parent | 714589c2742209cc228991b115e48548fb8d89cf (diff) | |
net/tcp: Consistently align TCP-AO option in the header
Currently functions that pre-calculate TCP header options length use
unaligned TCP-AO header + MAC-length for skb reservation.
And the functions that actually write TCP-AO options into skb do align
the header. Nothing good can come out of this for ((maclen % 4) != 0).
Provide tcp_ao_len_aligned() helper and use it everywhere for TCP
header options space calculations.
Fixes: 1e03d32bea8e ("net/tcp: Add TCP-AO sign to outgoing packets")
Signed-off-by: Dmitry Safonov <dima@arista.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
| -rw-r--r-- | include/net/tcp_ao.h | 6 | ||||
| -rw-r--r-- | net/ipv4/tcp_ao.c | 4 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 4 | ||||
| -rw-r--r-- | net/ipv4/tcp_minisocks.c | 2 | ||||
| -rw-r--r-- | net/ipv4/tcp_output.c | 6 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | 
6 files changed, 15 insertions, 9 deletions
| diff --git a/include/net/tcp_ao.h b/include/net/tcp_ao.h index b56be10838f0..647781080613 100644 --- a/include/net/tcp_ao.h +++ b/include/net/tcp_ao.h @@ -62,11 +62,17 @@ static inline int tcp_ao_maclen(const struct tcp_ao_key *key)  	return key->maclen;  } +/* Use tcp_ao_len_aligned() for TCP header calculations */  static inline int tcp_ao_len(const struct tcp_ao_key *key)  {  	return tcp_ao_maclen(key) + sizeof(struct tcp_ao_hdr);  } +static inline int tcp_ao_len_aligned(const struct tcp_ao_key *key) +{ +	return round_up(tcp_ao_len(key), 4); +} +  static inline unsigned int tcp_ao_digest_size(struct tcp_ao_key *key)  {  	return key->digest_size; diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c index 7696417d0640..c8be1d526eac 100644 --- a/net/ipv4/tcp_ao.c +++ b/net/ipv4/tcp_ao.c @@ -1100,7 +1100,7 @@ void tcp_ao_connect_init(struct sock *sk)  			ao_info->current_key = key;  		if (!ao_info->rnext_key)  			ao_info->rnext_key = key; -		tp->tcp_header_len += tcp_ao_len(key); +		tp->tcp_header_len += tcp_ao_len_aligned(key);  		ao_info->lisn = htonl(tp->write_seq);  		ao_info->snd_sne = 0; @@ -1346,7 +1346,7 @@ static int tcp_ao_parse_crypto(struct tcp_ao_add *cmd, struct tcp_ao_key *key)  	syn_tcp_option_space -= TCPOLEN_MSS_ALIGNED;  	syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED;  	syn_tcp_option_space -= TCPOLEN_WSCALE_ALIGNED; -	if (tcp_ao_len(key) > syn_tcp_option_space) { +	if (tcp_ao_len_aligned(key) > syn_tcp_option_space) {  		err = -EMSGSIZE;  		goto err_kfree;  	} diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 5f693bbd578d..0c50c5a32b84 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -690,7 +690,7 @@ static bool tcp_v4_ao_sign_reset(const struct sock *sk, struct sk_buff *skb,  	reply_options[0] = htonl((TCPOPT_AO << 24) | (tcp_ao_len(key) << 16) |  				 (aoh->rnext_keyid << 8) | keyid); -	arg->iov[0].iov_len += round_up(tcp_ao_len(key), 4); +	arg->iov[0].iov_len += tcp_ao_len_aligned(key);  	reply->doff = arg->iov[0].iov_len / 4;  	if (tcp_ao_hash_hdr(AF_INET, (char *)&reply_options[1], @@ -978,7 +978,7 @@ static void tcp_v4_send_ack(const struct sock *sk,  					  (tcp_ao_len(key->ao_key) << 16) |  					  (key->ao_key->sndid << 8) |  					  key->rcv_next); -		arg.iov[0].iov_len += round_up(tcp_ao_len(key->ao_key), 4); +		arg.iov[0].iov_len += tcp_ao_len_aligned(key->ao_key);  		rep.th.doff = arg.iov[0].iov_len / 4;  		tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset], diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index a9807eeb311c..9e85f2a0bddd 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c @@ -615,7 +615,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,  	ao_key = treq->af_specific->ao_lookup(sk, req,  				tcp_rsk(req)->ao_keyid, -1);  	if (ao_key) -		newtp->tcp_header_len += tcp_ao_len(ao_key); +		newtp->tcp_header_len += tcp_ao_len_aligned(ao_key);   #endif  	if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len)  		newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index eb13a55d660c..93eef1dbbc55 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -825,7 +825,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,  		timestamps = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_timestamps);  		if (tcp_key_is_ao(key)) {  			opts->options |= OPTION_AO; -			remaining -= tcp_ao_len(key->ao_key); +			remaining -= tcp_ao_len_aligned(key->ao_key);  		}  	} @@ -915,7 +915,7 @@ static unsigned int tcp_synack_options(const struct sock *sk,  			ireq->tstamp_ok &= !ireq->sack_ok;  	} else if (tcp_key_is_ao(key)) {  		opts->options |= OPTION_AO; -		remaining -= tcp_ao_len(key->ao_key); +		remaining -= tcp_ao_len_aligned(key->ao_key);  		ireq->tstamp_ok &= !ireq->sack_ok;  	} @@ -982,7 +982,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb  		size += TCPOLEN_MD5SIG_ALIGNED;  	} else if (tcp_key_is_ao(key)) {  		opts->options |= OPTION_AO; -		size += tcp_ao_len(key->ao_key); +		size += tcp_ao_len_aligned(key->ao_key);  	}  	if (likely(tp->rx_opt.tstamp_ok)) { diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 937a02c2e534..8c6623496dd7 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -881,7 +881,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32  	if (tcp_key_is_md5(key))  		tot_len += TCPOLEN_MD5SIG_ALIGNED;  	if (tcp_key_is_ao(key)) -		tot_len += tcp_ao_len(key->ao_key); +		tot_len += tcp_ao_len_aligned(key->ao_key);  #ifdef CONFIG_MPTCP  	if (rst && !tcp_key_is_md5(key)) { | 
