From: Eric Dumazet <edumazet@google.com>
To: "David S . Miller" <davem@davemloft.net>,
Jakub Kicinski <kuba@kernel.org>,
Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
Dmitry Safonov <0x7f454c46@gmail.com>,
Neal Cardwell <ncardwell@google.com>,
Kuniyuki Iwashima <kuniyu@google.com>,
netdev@vger.kernel.org, eric.dumazet@gmail.com,
Eric Dumazet <edumazet@google.com>
Subject: [PATCH net 1/2] tcp: fix TCP-AO key lookup precedence (shadowing)
Date: Mon, 22 Jun 2026 18:52:47 +0000 [thread overview]
Message-ID: <20260622185248.1717846-2-edumazet@google.com> (raw)
In-Reply-To: <20260622185248.1717846-1-edumazet@google.com>
TCP-AO implementation stores Master Key Tuples (MKTs) in an unsorted
doubly-linked list (ao_info->head) and inserts new keys at the head.
When looking up a key, __tcp_ao_do_lookup() walks this list and returns
the first match it finds.
Because the list is unsorted, a newer, less-specific key can shadow an
older, more-specific key if it happens to be inserted later. This leads
to incorrect key selection in two scenarios:
1. VRF Shadowing: A wildcard VRF key (not bound to an interface) added
after a VRF-specific key will shadow the VRF-specific key for traffic
arriving on that VRF.
2. Prefix Shadowing: A less-specific prefix key (e.g., /24) added after
a more-specific prefix key (e.g., /32) will shadow the more-specific
key during outbound connection establishment.
Unlike TCP MD5, which walks the entire list and evaluates the "best
match" using better_md5_match(), TCP-AO expects the list order to
determine precedence.
Fix this by implementing sorted insertion in tcp_ao_link_mkt(). Keys
are inserted in descending order of specificity:
- VRF-bound keys take precedence over unbound keys.
- Longer prefix matches (LPM) take precedence over shorter ones.
This preserves the performance of the lockless RX lookup path (early
return on first match) while ensuring correct precedence.
Fixes: 4954f17ddefc ("net/tcp: Introduce TCP_AO setsockopt()s")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Assisted-by: Gemini:gemini-3.1-pro
---
net/ipv4/tcp_ao.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/tcp_ao.c b/net/ipv4/tcp_ao.c
index 2f69bcecae78a677f33033a2d30e09a8ff858ad8..2d10fb1dd4cf87cc79ef5b5ead80eb3048218250 100644
--- a/net/ipv4/tcp_ao.c
+++ b/net/ipv4/tcp_ao.c
@@ -341,9 +341,34 @@ static struct tcp_ao_info *tcp_ao_alloc_info(gfp_t flags)
return ao;
}
+static bool tcp_ao_key_is_more_specific(const struct tcp_ao_key *a,
+ const struct tcp_ao_key *b)
+{
+ bool a_vrf = !!(a->keyflags & TCP_AO_KEYF_IFINDEX);
+ bool b_vrf = !!(b->keyflags & TCP_AO_KEYF_IFINDEX);
+
+ if (a_vrf != b_vrf)
+ return a_vrf; /* VRF-bound is more specific */
+
+ return a->prefixlen > b->prefixlen; /* Longer prefix is more specific */
+}
+
static void tcp_ao_link_mkt(struct tcp_ao_info *ao, struct tcp_ao_key *mkt)
{
- hlist_add_head_rcu(&mkt->node, &ao->head);
+ struct tcp_ao_key *pos;
+ struct hlist_node *last = NULL;
+
+ hlist_for_each_entry(pos, &ao->head, node) {
+ if (tcp_ao_key_is_more_specific(mkt, pos)) {
+ hlist_add_before_rcu(&mkt->node, &pos->node);
+ return;
+ }
+ last = &pos->node;
+ }
+ if (last)
+ hlist_add_behind_rcu(&mkt->node, last);
+ else
+ hlist_add_head_rcu(&mkt->node, &ao->head);
}
static struct tcp_ao_key *tcp_ao_copy_key(struct sock *sk,
--
2.55.0.rc0.799.gd6f94ed593-goog
next prev parent reply other threads:[~2026-06-22 18:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-22 18:52 [PATCH net 0/2] tcp: make TCP-AO lookups more predictable Eric Dumazet
2026-06-22 18:52 ` Eric Dumazet [this message]
2026-06-22 18:52 ` [PATCH net 2/2] selftests/net: Add TCP-AO key shadowing test Eric Dumazet
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260622185248.1717846-2-edumazet@google.com \
--to=edumazet@google.com \
--cc=0x7f454c46@gmail.com \
--cc=davem@davemloft.net \
--cc=eric.dumazet@gmail.com \
--cc=horms@kernel.org \
--cc=kuba@kernel.org \
--cc=kuniyu@google.com \
--cc=ncardwell@google.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox