ipn/ipnlocal, types/netmap, tsnet: filter unsigned peers on delta path

aa5da2e5f2 (in the 1.99.x dev series, unstable) introduced some bugs,
only some of which were later fixed. This fixed another. As of that
change, tkaFilterNetmapLocked ran only on full netmaps through
LocalBackend.setClientStatusLocked and not peer upserts via new or
changed peers. The later ae743642d9 fixed a regression in the
Engine layer but didn't fix the tkaFilter code from re-running on
upserts.

This add a tkaFilterDeltaMutsLocked pass before
nodeBackend.UpdateNetmapDelta. For each NodeMutationUpsert whose
peer fails the same signature check tkaFilterNetmapLocked applies,
rewrite the upsert in place into a NodeMutationRemove targeting the
same node ID, so magicsock's per-mutation dispatch and
nodeBackend.peers both drop the peer, matching the prior full-netmap
semantics.

New tsnet tests added:

  - TestTailnetLockFiltersUnsignedDeltaPeer covers the new-peer
    case.
  - TestTailnetLockFiltersUnsignedDeltaPeerReplacement covers the
    existing-peer-replacement case, to an empty signature.
  - TestTailnetLockFiltersDeltaPeerWithInvalidSignature like above
    but with a bogus signature.

Updates #12542
Updates tailscale/corp#43767

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Ib35d0391541fee654867c26489847dbc5b7e2ae8
This commit is contained in:
Brad Fitzpatrick
2026-06-23 08:12:36 -07:00
committed by Brad Fitzpatrick
parent 0b551986fe
commit af2f228a18
5 changed files with 481 additions and 7 deletions
+9
View File
@@ -2443,6 +2443,15 @@ func (b *LocalBackend) UpdateNetmapDelta(muts []netmap.NodeMutation) (handled bo
defer b.mu.Unlock()
cn := b.currentNode()
// Filter the mutations through tailnet lock before applying them.
// Unsigned (or invalidly-signed) peers arriving via PeersChanged
// ride the delta path as NodeMutationUpsert and would otherwise
// land in nodeBackend.peers without ever passing through
// tkaFilterNetmapLocked. tkaFilterDeltaMutsLocked rewrites any
// such upsert into a NodeMutationRemove for the same node ID, so
// any previously-signed peer at that ID is also evicted, matching
// the full-netmap behavior of [tkaFilterNetmapLocked].
muts = b.tkaFilterDeltaMutsLocked(muts)
needsAuthReconfig := netmapDeltaNeedsAuthReconfig(cn, muts)
cn.UpdateNetmapDelta(muts)