fix: prevent self-referential DNS backup on re-install #40

Merged
razvandimescu merged 7 commits from fix/stale-dns-backup into main 2026-04-08 21:38:38 +08:00
razvandimescu commented 2026-04-08 09:19:25 +08:00 (Migrated from github.com)

Summary

numa install previously captured current system DNS servers verbatim into the backup file. If numa was already installed, current DNS was 127.0.0.1, so the "backup" recorded 127.0.0.1 as the "original" — making a subsequent numa uninstall a no-op self-reference.

Reproduced during v0.10.0 brew dogfood: after sudo numa uninstall (which removed the backup) then sudo /opt/homebrew/bin/numa install (which re-captured, but system DNS was still 127.0.0.1 from a prior install that hadn't been cleanly reverted), sudo numa uninstall printed:

restored DNS for "Wi-Fi" -> 127.0.0.1

Fix

All three platforms, same pattern:

  • macOS / Windows: if the existing backup already contains ≥1 non-loopback/non-stub upstream, preserve it as-is. Otherwise, capture fresh but filter loopback/stub addresses before writing, so a capture from already-numa-managed state isn't self-referential.
  • Linux (resolv.conf fallback): detect numa-managed or all-loopback resolv.conf and skip the file copy; preserve an existing useful backup. The systemd-resolved path is unaffected (it uses a drop-in, no backup file).

Tests

Three new unit tests cover the predicates:

  • macos_backup_real_upstream_detectionHashMap with empty, all-loopback, and mixed entries
  • windows_backup_filters_loopback — filter logic on WindowsInterfaceDns (added in a follow-up commit, reviewed for parity with the macOS test)
  • resolv_conf_real_upstream_detection — real upstream, self-referential, numa marker, systemd stub (127.0.0.53), and mixed content

All 130 existing + new tests pass locally and on CI.

Test plan

  • CI green across Linux, macOS, Windows
  • On a numa-installed machine, sudo numa install a second time reports Existing DNS backup preserved and leaves the backup file untouched. Verified manually on macOS with a fabricated {"Wi-Fi": ["1.1.1.1", "8.8.8.8"]} backup (the dogfood machine had been numa-managed long enough that no useful pre-numa backup existed naturally — the predicate path that fires the preserve branch needs ≥1 non-loopback upstream in the existing file).
  • After manually deleting a stale self-referential backup, a fresh sudo numa install captures real upstreams (or empty = DHCP) rather than 127.0.0.1. Verified manually on macOS — the resulting backup contained {"Wi-Fi": [], ...} (filtered loopback → empty → restore-to-DHCP), not the buggy {"Wi-Fi": ["127.0.0.1"]} that v0.10.0 produced.
## Summary `numa install` previously captured current system DNS servers verbatim into the backup file. If numa was already installed, current DNS was `127.0.0.1`, so the "backup" recorded `127.0.0.1` as the "original" — making a subsequent `numa uninstall` a no-op self-reference. Reproduced during v0.10.0 brew dogfood: after `sudo numa uninstall` (which removed the backup) then `sudo /opt/homebrew/bin/numa install` (which re-captured, but system DNS was still 127.0.0.1 from a prior install that hadn't been cleanly reverted), `sudo numa uninstall` printed: ``` restored DNS for "Wi-Fi" -> 127.0.0.1 ``` ## Fix All three platforms, same pattern: - **macOS / Windows**: if the existing backup already contains ≥1 non-loopback/non-stub upstream, preserve it as-is. Otherwise, capture fresh but filter loopback/stub addresses before writing, so a capture from already-numa-managed state isn't self-referential. - **Linux (resolv.conf fallback)**: detect numa-managed or all-loopback resolv.conf and skip the file copy; preserve an existing useful backup. The systemd-resolved path is unaffected (it uses a drop-in, no backup file). ## Tests Three new unit tests cover the predicates: - `macos_backup_real_upstream_detection` — `HashMap` with empty, all-loopback, and mixed entries - `windows_backup_filters_loopback` — filter logic on `WindowsInterfaceDns` (added in a follow-up commit, reviewed for parity with the macOS test) - `resolv_conf_real_upstream_detection` — real upstream, self-referential, numa marker, systemd stub (127.0.0.53), and mixed content All 130 existing + new tests pass locally and on CI. ## Test plan - [x] CI green across Linux, macOS, Windows - [x] On a numa-installed machine, `sudo numa install` a second time reports `Existing DNS backup preserved` and leaves the backup file untouched. Verified manually on macOS with a fabricated `{"Wi-Fi": ["1.1.1.1", "8.8.8.8"]}` backup (the dogfood machine had been numa-managed long enough that no useful pre-numa backup existed naturally — the predicate path that fires the preserve branch needs ≥1 non-loopback upstream in the existing file). - [x] After manually deleting a stale self-referential backup, a fresh `sudo numa install` captures real upstreams (or empty = DHCP) rather than 127.0.0.1. Verified manually on macOS — the resulting backup contained `{"Wi-Fi": [], ...}` (filtered loopback → empty → restore-to-DHCP), not the buggy `{"Wi-Fi": ["127.0.0.1"]}` that v0.10.0 produced.
Sign in to join this conversation.