Files
fips/src/cache
Johnathan Corgan a9ee4bf2f0 fix(cache): let a verified coordinate refuse an unauthenticated hint
A coordinate learned by warming and one established by a lookup whose proof
this node checked were until now the same thing, so a forged warm silently
displaced a verified entry. Entries now carry their provenance, and a hint
does not overwrite a live verified one.

Hint is the default at every level. CacheEntry::new produces one, update
demotes to one, and CoordCache::insert takes hint semantics under the
obvious name. Conferring trust has to be asked for, by calling
insert_verified or insert_verified_with_path_mtu, which only the lookup
response handler does. That way the safe write is what a caller gets by
reaching for the name they would reach for anyway, rather than the opt-in.

HintOutcome is #[must_use], which turned out to be the useful part. It made
the compiler, not review, enumerate every production hint write: the warming
funnel, the CP-flag local delivery, and the initiator-side SessionAck. That
matched the enumeration done by reading, which is the only reason I trust
either.

Verification runs on its own clock and is never refreshed. An entry carrying
live traffic is refreshed on every use and so never expires, and if
verification rode that clock a once-verified entry would outrank every hint
forever, including the hints carrying a destination's genuine move. After
VERIFIED_TTL_MS the coordinates stay usable and simply stop winning.

Eviction will not take a live verified entry while any unverified one
remains, and declines rather than growing past the cap when they are all
verified. Without that, the precedence rule is bypassable: fill the cache
with hints until a verified entry becomes the LRU, evict it, and plant into
a slot that now accepts an ordinary first write. That is the shape that got
the earlier attempt on fix/coord-cache-provenance rejected.

Sixty-nine test call sites are seeds whose outcome cannot be Rejected, since
no verified entry exists in any of those caches; insert_verified appears
outside the cache module in exactly three places, two of them tests of their
own. They take the outcome explicitly.

Break-checked. Disabling the precedence rule reds three tests including the
end-to-end one driven through handle_session_datagram; disabling the
eviction restriction reds the two that cover it. The healthy path stays
green at 2202 tests.

Still mitigation. A destination that was never verified holds only hints, so
hint-over-hint is unchanged, and the delete-then-plant sequence still runs
against one end of a live session.
2026-08-24 10:38:51 +01:00
..