tcp_v4_send_ack() and tcp_v6_send_response() construct standalone TCP responses with TCP-AO options. The option length carries the actual MAC length, but the TCP header length includes the option rounded up to a four-byte boundary. tcp_ao_hash_hdr() writes the MAC only. Thus, when the MAC length is not four-byte aligned, the one to three bytes after the MAC are left uninitialized and may be transmitted. For the normal TCP-AO hashing mode, those bytes also have to be initialized before computing the MAC. Initialize only the alignment padding in the TCP-AO branches, before hashing the header. Use TCPOPT_NOP, as in the normal TCP-AO output path. This avoids adding work to non-AO TCP responses while preserving a valid authenticated header. Fixes: decde2586b34 ("net/tcp: Add TCP-AO sign to twsk") Fixes: da7dfaa6d6f7 ("net/tcp: Consistently align TCP-AO option in the header") Cc: stable@vger.kernel.org Reported-by: Yizhou Zhao Reported-by: Yuxiang Yang Reported-by: Ao Wang Reported-by: Xuewei Feng Reported-by: Qi Li Reported-by: Ke Xu Assisted-by: Claude-Code:GLM-5.2-special Suggested-by: Eric Dumazet Signed-off-by: Yizhou Zhao --- Changes in v2: - Fix TCP-AO path only to avoid slowing down other TCP paths, suggested by Eric. - Fix the IPv6 path either. - Link to v1: https://lore.kernel.org/netdev/20260713081842.3119-1-zhaoyz24@mails.tsinghua.edu.cn/ --- net/ipv4/tcp_ipv4.c | 3 +++ net/ipv6/tcp_ipv6.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 209ef7522508..2f6ff630a0e5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -971,6 +971,9 @@ static void tcp_v4_send_ack(const struct sock *sk, key->rcv_next); arg.iov[0].iov_len += tcp_ao_len_aligned(key->ao_key); rep.th.doff = arg.iov[0].iov_len / 4; + memset((u8 *)&rep.opt[offset] + tcp_ao_maclen(key->ao_key), + TCPOPT_NOP, tcp_ao_len_aligned(key->ao_key) - + tcp_ao_len(key->ao_key)); tcp_ao_hash_hdr(AF_INET, (char *)&rep.opt[offset], key->ao_key, key->traffic_key, diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index ebe161d72fbd..0bc89014653d 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -923,6 +923,8 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 (tcp_ao_len(key->ao_key) << 16) | (key->ao_key->sndid << 8) | (key->rcv_next)); + memset((u8 *)topt + tcp_ao_maclen(key->ao_key), TCPOPT_NOP, + tcp_ao_len_aligned(key->ao_key) - tcp_ao_len(key->ao_key)); tcp_ao_hash_hdr(AF_INET6, (char *)topt, key->ao_key, key->traffic_key, -- 2.47.3