Commit da7dfaa6 authored by Dmitry Safonov's avatar Dmitry Safonov Committed by Paolo Abeni

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: 1e03d32b ("net/tcp: Add TCP-AO sign to outgoing packets")
Signed-off-by: default avatarDmitry Safonov <dima@arista.com>
Reviewed-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 714589c2
...@@ -62,11 +62,17 @@ static inline int tcp_ao_maclen(const struct tcp_ao_key *key) ...@@ -62,11 +62,17 @@ static inline int tcp_ao_maclen(const struct tcp_ao_key *key)
return key->maclen; return key->maclen;
} }
/* Use tcp_ao_len_aligned() for TCP header calculations */
static inline int tcp_ao_len(const struct tcp_ao_key *key) static inline int tcp_ao_len(const struct tcp_ao_key *key)
{ {
return tcp_ao_maclen(key) + sizeof(struct tcp_ao_hdr); 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) static inline unsigned int tcp_ao_digest_size(struct tcp_ao_key *key)
{ {
return key->digest_size; return key->digest_size;
......
...@@ -1100,7 +1100,7 @@ void tcp_ao_connect_init(struct sock *sk) ...@@ -1100,7 +1100,7 @@ void tcp_ao_connect_init(struct sock *sk)
ao_info->current_key = key; ao_info->current_key = key;
if (!ao_info->rnext_key) if (!ao_info->rnext_key)
ao_info->rnext_key = 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->lisn = htonl(tp->write_seq);
ao_info->snd_sne = 0; 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) ...@@ -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_MSS_ALIGNED;
syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED; syn_tcp_option_space -= TCPOLEN_TSTAMP_ALIGNED;
syn_tcp_option_space -= TCPOLEN_WSCALE_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; err = -EMSGSIZE;
goto err_kfree; goto err_kfree;
} }
......
...@@ -690,7 +690,7 @@ static bool tcp_v4_ao_sign_reset(const struct sock *sk, struct sk_buff *skb, ...@@ -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) | reply_options[0] = htonl((TCPOPT_AO << 24) | (tcp_ao_len(key) << 16) |
(aoh->rnext_keyid << 8) | keyid); (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; reply->doff = arg->iov[0].iov_len / 4;
if (tcp_ao_hash_hdr(AF_INET, (char *)&reply_options[1], 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, ...@@ -978,7 +978,7 @@ static void tcp_v4_send_ack(const struct sock *sk,
(tcp_ao_len(key->ao_key) << 16) | (tcp_ao_len(key->ao_key) << 16) |
(key->ao_key->sndid << 8) | (key->ao_key->sndid << 8) |
key->rcv_next); 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; rep.th.doff = arg.iov[0].iov_len / 4;
tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset], tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset],
......
...@@ -615,7 +615,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk, ...@@ -615,7 +615,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
ao_key = treq->af_specific->ao_lookup(sk, req, ao_key = treq->af_specific->ao_lookup(sk, req,
tcp_rsk(req)->ao_keyid, -1); tcp_rsk(req)->ao_keyid, -1);
if (ao_key) if (ao_key)
newtp->tcp_header_len += tcp_ao_len(ao_key); newtp->tcp_header_len += tcp_ao_len_aligned(ao_key);
#endif #endif
if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len) if (skb->len >= TCP_MSS_DEFAULT + newtp->tcp_header_len)
newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len;
......
...@@ -825,7 +825,7 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb, ...@@ -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); timestamps = READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_timestamps);
if (tcp_key_is_ao(key)) { if (tcp_key_is_ao(key)) {
opts->options |= OPTION_AO; 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, ...@@ -915,7 +915,7 @@ static unsigned int tcp_synack_options(const struct sock *sk,
ireq->tstamp_ok &= !ireq->sack_ok; ireq->tstamp_ok &= !ireq->sack_ok;
} else if (tcp_key_is_ao(key)) { } else if (tcp_key_is_ao(key)) {
opts->options |= OPTION_AO; 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; ireq->tstamp_ok &= !ireq->sack_ok;
} }
...@@ -982,7 +982,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb ...@@ -982,7 +982,7 @@ static unsigned int tcp_established_options(struct sock *sk, struct sk_buff *skb
size += TCPOLEN_MD5SIG_ALIGNED; size += TCPOLEN_MD5SIG_ALIGNED;
} else if (tcp_key_is_ao(key)) { } else if (tcp_key_is_ao(key)) {
opts->options |= OPTION_AO; 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)) { if (likely(tp->rx_opt.tstamp_ok)) {
......
...@@ -881,7 +881,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 ...@@ -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)) if (tcp_key_is_md5(key))
tot_len += TCPOLEN_MD5SIG_ALIGNED; tot_len += TCPOLEN_MD5SIG_ALIGNED;
if (tcp_key_is_ao(key)) 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 #ifdef CONFIG_MPTCP
if (rst && !tcp_key_is_md5(key)) { if (rst && !tcp_key_is_md5(key)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment