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

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
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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;
	}
+2 −2
Original line number Diff line number Diff line
@@ -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],
+1 −1
Original line number Diff line number Diff line
@@ -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;
+3 −3
Original line number Diff line number Diff line
@@ -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)) {
Loading