Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
163 commits
Select commit Hold shift + click to select a range
34724ad
docs(netlink): plan the link kinds and 7.2.0's link set inet (goip-li…
randomizedcoder Oct 24, 2026
7296291
feat(microvms): late kind modules, no fallback tunnels, a kind probe;…
randomizedcoder Oct 24, 2026
7aa7875
feat(microvms): capture iproute2 7.2.0's link set inet; close KC1 (KC…
randomizedcoder Oct 24, 2026
5a867ac
feat(microvms): a kind write corpus, with bridge's rows (KC2-T01)
randomizedcoder Oct 24, 2026
9a4208f
feat(microvms): bridge_slave's write rows; close KC2, plan KC3 (KC2-T02)
randomizedcoder Oct 24, 2026
002ca4f
feat(microvms): vlan's write rows (KC3-T01)
randomizedcoder Oct 24, 2026
4cd88b9
feat(microvms): macvlan's and macvtap's write rows (KC3-T02)
randomizedcoder Oct 24, 2026
1d84888
feat(microvms): ipvlan's and ipvtap's write rows; close KC3, plan KC4…
randomizedcoder Oct 24, 2026
1a18bd4
feat(microvms): vxlan's write rows (KC4-T01)
randomizedcoder Oct 24, 2026
b316eb5
feat(microvms): geneve's write rows (KC4-T02)
randomizedcoder Oct 25, 2026
cc2177a
feat(microvms): bareudp's and amt's write rows (KC4-T03)
randomizedcoder Oct 25, 2026
5ef5a8f
feat(microvms): gtp's write rows; close KC4, plan KC5 (KC4-T04)
randomizedcoder Oct 25, 2026
76a8dce
feat(microvms): gre's, gretap's and erspan's write rows (KC5-T01)
randomizedcoder Oct 25, 2026
30d678a
feat(microvms): ip6gre's, ip6gretap's and ip6erspan's write rows (KC5…
randomizedcoder Oct 25, 2026
74625a2
feat(microvms): ipip's and sit's write rows (KC5-T03)
randomizedcoder Oct 25, 2026
1607b57
feat(microvms): ip6tnl's write rows (KC5-T04)
randomizedcoder Oct 25, 2026
87a7c33
feat(microvms): vti's, vti6's and xfrm's write rows; close KC5, plan …
randomizedcoder Oct 25, 2026
6f8e72f
feat(microvms): hsr's write rows (KC6-T01)
randomizedcoder Oct 25, 2026
95b5c6d
feat(microvms): netkit's write rows (KC6-T02)
randomizedcoder Oct 25, 2026
0a7e747
feat(microvms): vrf's, vrf_slave's and vxcan's write rows (KC6-T03)
randomizedcoder Oct 25, 2026
efc887b
feat(microvms): batadv's and the parser-less kinds' write rows; close…
randomizedcoder Oct 25, 2026
b06f338
test(xtcpnl): commit the 7.3.0 link-write corpus with the kind rows (…
randomizedcoder Oct 25, 2026
5f8188e
test(xtcpnl): the link kind completeness gate; close KC7 and the KC t…
randomizedcoder Oct 25, 2026
1e132f4
feat(xtcpnl): the inet devconf codec; close KP0, plan KP1 (KP0-T01)
randomizedcoder Oct 25, 2026
a38c3ba
feat(xtcpnl): the bridge codec (KP1-T01)
randomizedcoder Oct 25, 2026
f30533e
feat(xtcpnl): the bridge_slave codec; close KP1, plan KP2 (KP1-T02)
randomizedcoder Oct 25, 2026
5562cb9
feat(xtcpnl): the vlan codec (KP2-T01)
randomizedcoder Oct 25, 2026
4808e67
feat(xtcpnl): the macvlan and macvtap codec (KP2-T02)
randomizedcoder Oct 25, 2026
242e187
feat(xtcpnl): the ipvlan and ipvtap codec; close KP2, plan KP3 (KP2-T03)
randomizedcoder Oct 25, 2026
68e09d7
feat(xtcpnl): the vxlan codec (KP3-T01)
randomizedcoder Oct 25, 2026
4d3b8a2
feat(xtcpnl): the geneve codec (KP3-T02)
randomizedcoder Oct 25, 2026
8b656f9
feat(xtcpnl): the bareudp and amt codecs (KP3-T03)
randomizedcoder Oct 25, 2026
03bd2c2
feat(xtcpnl): the gtp codec; close KP3, plan KP4 (KP3-T04)
randomizedcoder Oct 25, 2026
404fb94
feat(xtcpnl): the gre, gretap and erspan codec (KP4-T01)
randomizedcoder Oct 25, 2026
d708a5c
feat(xtcpnl): the ip6gre, ip6gretap and ip6erspan encoder (KP4-T02)
randomizedcoder Oct 25, 2026
6fa3e4e
feat(xtcpnl): the ipip and sit codec (KP4-T03)
randomizedcoder Oct 25, 2026
339ce61
feat(xtcpnl): the ip6tnl encoder (KP4-T04)
randomizedcoder Oct 25, 2026
94e0219
feat(xtcpnl): the vti, vti6 and xfrm codecs; close KP4, plan KP5 (KP4…
randomizedcoder Oct 25, 2026
596cd77
feat(xtcpnl): the hsr codec (KP5-T01)
randomizedcoder Oct 25, 2026
50159b7
feat(xtcpnl): the netkit codec (KP5-T02)
randomizedcoder Oct 25, 2026
b4290ce
feat(xtcpnl): the vrf and vxcan encoders, vrf_slave checks (KP5-T03)
randomizedcoder Oct 25, 2026
f74585a
feat(xtcpnl): the batadv encoder; close KP5, plan KG0 (KP5-T04)
randomizedcoder Oct 25, 2026
dad3783
feat(goip): ip link set … inet (KG0-T01)
randomizedcoder Oct 25, 2026
16e6d5e
feat(goipparity): -section, to run one ip object's rows
randomizedcoder Oct 25, 2026
09e0878
feat(goipparity): the inet matrix rows, gated (KG0-T02)
randomizedcoder Oct 25, 2026
6cf7fe6
docs(goip-kinds): plan KG1, goip bridge (DOC016)
randomizedcoder Oct 25, 2026
81bd96d
feat(goip): the bridge words (KG1-T01)
randomizedcoder Oct 25, 2026
652751e
feat(goip): the bridge_slave words (KG1-T02)
randomizedcoder Oct 25, 2026
f1b4b41
feat(goip): the bridge's -d output (KG1-T03)
randomizedcoder Oct 25, 2026
7b5a194
feat(goip): the bridge port's -d output (KG1-T04)
randomizedcoder Oct 25, 2026
7ab72d2
feat(goipparity): the bridge matrix rows, gated (KG1-T05)
randomizedcoder Oct 26, 2026
4b6a4ef
docs(goip-kinds): plan KG2, goip VLAN family (DOC017)
randomizedcoder Oct 26, 2026
548e5b2
feat(goip): the link keyword and the vlan words (KG2-T01)
randomizedcoder Oct 26, 2026
f5de9c6
feat(goip): the macvlan and macvtap words (KG2-T02)
randomizedcoder Oct 26, 2026
5d39a76
feat(goip): the ipvlan and ipvtap words (KG2-T03)
randomizedcoder Oct 26, 2026
c4ca672
feat(goip): the VLAN family's -d output (KG2-T04)
randomizedcoder Oct 26, 2026
3635ed8
feat(goipparity): the VLAN family matrix rows, gated (KG2-T05)
randomizedcoder Oct 26, 2026
6b4ee99
docs(goip-kinds): plan KG3, goip UDP overlays (DOC018)
randomizedcoder Oct 26, 2026
bac28ce
feat(goip): the vxlan words (KG3-T01)
randomizedcoder Oct 26, 2026
005fa7b
feat(goip): the geneve words (KG3-T02)
randomizedcoder Oct 26, 2026
a37e67d
feat(goip): the bareudp, amt and gtp words (KG3-T03)
randomizedcoder Oct 26, 2026
c6cb320
feat(goip): the UDP overlays' -d output (KG3-T04)
randomizedcoder Oct 26, 2026
1e9df98
feat(goipparity): the UDP overlay matrix rows, gated (KG3-T05)
randomizedcoder Oct 26, 2026
0ca9630
docs(goip-kinds): plan KG4, goip IP tunnels (DOC019)
randomizedcoder Oct 26, 2026
d61ff6b
feat(goipparity): no fallback tunnels before the first row (KG4-T01)
randomizedcoder Oct 26, 2026
072d1f3
feat(nlcap): BIRD's bridge FDB, VLAN and MPLS captures; per-section l…
randomizedcoder Nov 1, 2026
20fcc74
feat(xtcpnl): parse bridge FDB, bridge VLAN and MPLS for BIRD (B2, B3)
randomizedcoder Nov 1, 2026
70fc28d
feat(nlcap): every link and address of the namespaces BIRD reads (B4)
randomizedcoder Nov 1, 2026
f90a2c4
docs(nlcap): keep flake.lock, the kernel and iproute2 moving forward
randomizedcoder Nov 1, 2026
93a474a
feat(nlcap): an ssh-driven nl_mon workbench and the JSONL rows it run…
randomizedcoder Nov 1, 2026
2252358
feat(nlcap): tc from tdc, the tc parsers and their oracles (W1)
randomizedcoder Nov 1, 2026
bb0a1c3
feat(nlcap): a pairwise grammar matrix and ip route rows with O3/O4 (…
randomizedcoder Nov 1, 2026
e1b594f
feat(nlcap): ip rule and ip nexthop matrix rows with O3/O4 (W2b)
randomizedcoder Nov 1, 2026
54b9724
feat(goip): O5, a goip differential over the route, rule and nexthop …
randomizedcoder Nov 1, 2026
c8154e4
feat(nlcap): rows mined from the fib selftests, with O5 over them (W2d)
randomizedcoder Nov 1, 2026
ea40b42
feat(nlcap): ip address matrix rows with O3/O4/O5 (W3a)
randomizedcoder Nov 1, 2026
5aded6b
feat(nlcap): ip neigh matrix rows with O3/O4/O5 (W3b)
randomizedcoder Nov 1, 2026
8683d79
feat(nlcap): ip link set matrix rows with O3/O4/O5 (W3c)
randomizedcoder Nov 1, 2026
84f9ce5
feat(nlcap): ip link add matrix rows with O3/O4/O5 (W3d)
randomizedcoder Nov 1, 2026
26c998c
feat(nlcap): a netlink coverage report against the kernel's policy ta…
randomizedcoder Nov 1, 2026
75fedde
feat(nlcap): ip route get rows for the route attributes no write send…
randomizedcoder Nov 1, 2026
1cb9f5b
test(xtcpnl): raise the workbench corpus budget to 64 MB
randomizedcoder Nov 1, 2026
4a1e671
feat(nlcap): rows for the link keywords no row sent (W4c)
randomizedcoder Nov 1, 2026
45f5146
feat(nlcap): bridge fdb rows for the neighbor attributes ip never sen…
randomizedcoder Nov 1, 2026
f9cadfa
feat(nlcap): bridge mdb rows, parsers and oracles (W5b)
randomizedcoder Nov 1, 2026
860f675
feat(nlcap): ss sock_diag rows, bytecode parser and oracles (W5c)
randomizedcoder Nov 1, 2026
e750191
feat(nlcap): ethtool rows, coalesce decoder and oracles (W5d)
randomizedcoder Nov 1, 2026
15bae7c
feat(goip): tunnel prefetch and gre/gretap/erspan words (KG4-T02)
randomizedcoder Nov 2, 2026
333388b
feat(goip): ip6gre, ip6gretap and ip6erspan words (KG4-T03)
randomizedcoder Nov 2, 2026
a60bb94
feat(goip): ipip and sit words (KG4-T04)
randomizedcoder Nov 2, 2026
d247e2b
feat(goip): ip6tnl words (KG4-T05)
randomizedcoder Nov 2, 2026
35d5fc9
feat(goip): vti, vti6 and xfrm words (KG4-T06)
randomizedcoder Nov 2, 2026
25fe7f4
feat(goip): the gre kinds' -d output (KG4-T07)
randomizedcoder Nov 2, 2026
1b936fa
feat(goip): the other tunnels' -d output (KG4-T08)
randomizedcoder Nov 2, 2026
7bbb9c1
feat(goipparity): the IP tunnel matrix rows (KG4-T09)
randomizedcoder Nov 2, 2026
8b9f1a0
docs(goip-link-kinds): break KG5 into tasks (DOC020)
randomizedcoder Nov 2, 2026
7a4ff7b
docs(goip-link-kinds): record the clean full run (V222)
randomizedcoder Nov 2, 2026
59c5da7
feat(goip): the kinds with no parser, and vrf and the queue keywords …
randomizedcoder Nov 2, 2026
c589c07
feat(goip): the hsr words (KG5-T02)
randomizedcoder Nov 2, 2026
53f1338
feat(goip): the netkit words (KG5-T03)
randomizedcoder Nov 2, 2026
0c780de
feat(goip): the vrf, vxcan and batadv words (KG5-T04)
randomizedcoder Nov 2, 2026
a1d6764
feat(goip): the bond parsers' statuses (KG5-T05)
randomizedcoder Nov 2, 2026
e802fc6
feat(goip): hsr's and netkit's -d output (KG5-T06)
randomizedcoder Nov 2, 2026
78ae084
fix(lint): replace the gosec suppressions with checked conversions
randomizedcoder Nov 2, 2026
d268aee
docs(static-analysis): record the 474 G115 sites the exclusion hides
randomizedcoder Nov 2, 2026
3a8bc8e
feat(goipparity): the remaining kinds' matrix rows, gated (KG5-T07)
randomizedcoder Nov 2, 2026
36aed93
docs(goip-link-kinds): the full parity run before the KG5 push (V246)
randomizedcoder Nov 2, 2026
01c37b6
fix(xtcp2): carry the soft restart's secrets in a sealed memfd, rebui…
randomizedcoder Nov 2, 2026
4da0e47
fix(linkmonitor): digest replayed values without their zero fields
randomizedcoder Nov 2, 2026
65daee4
docs(goip-write-keywords): plan the 608 write keywords goip refuses (…
randomizedcoder Nov 3, 2026
e9a397d
feat(goip): route nhid as RTA_NH_ID (GW1-T01)
randomizedcoder Nov 3, 2026
5123885
feat(goip): route pref and expires (GW1-T02)
randomizedcoder Nov 3, 2026
986e62b
feat(goip): route tos/dsfield, realms and vrf (GW1-T03)
randomizedcoder Nov 3, 2026
acbabfe
feat(goip): route multipath nexthop; close GW1 (GW1-T04)
randomizedcoder Nov 3, 2026
a19f251
feat(goip): link set address length check (GW2-T01)
randomizedcoder Nov 3, 2026
ea22a6e
feat(goip): link group, and the group-wide set (GW2-T02)
randomizedcoder Nov 3, 2026
20249af
feat(goip): link GSO and GRO sizes (GW2-T03)
randomizedcoder Nov 3, 2026
0ff083e
feat(goip): link addrgenmode (GW2-T04)
randomizedcoder Nov 3, 2026
6775997
feat(goip): link protodown and protodown_reason (GW2-T05)
randomizedcoder Nov 3, 2026
938d22f
feat(goip): link broadcast, carrier, mode and state (GW2-T06)
randomizedcoder Nov 3, 2026
763c463
feat(goip): link xdp off (GW2-T07)
randomizedcoder Nov 3, 2026
73183cd
feat(goip): link index, link-netnsid and parentdev; close GW2 (GW2-T08)
randomizedcoder Nov 3, 2026
32a1ad8
feat(goip): nexthop hw_stats (GW3-T01)
randomizedcoder Nov 3, 2026
f08fea4
feat(goip): refuse nexthop dst_port as ip 7.2.0 does (GW3-T02)
randomizedcoder Nov 3, 2026
2b048e7
feat(goip): nexthop encap mpls; close GW3 (GW3-T03)
randomizedcoder Nov 3, 2026
092b72a
feat(goip): rule realms; close GW4 (GW4-T01)
randomizedcoder Nov 3, 2026
d017fb8
test(goipparity): GW route matrix rows (GW5-T01)
randomizedcoder Nov 3, 2026
d9d040a
test(goipparity): GW link matrix rows (GW5-T02)
randomizedcoder Nov 3, 2026
e4f7787
test(goipparity): GW nexthop and rule matrix rows (GW5-T03)
randomizedcoder Nov 3, 2026
9149bed
test(goipparity): gate the GW matrix rows; close GW5 and the plan (GW…
randomizedcoder Nov 3, 2026
f84b1a1
docs(netlink): plan live rows for the keyword forms only O5 checks
randomizedcoder Nov 3, 2026
8d56c16
feat(nlcap): kwlive rows for the keyword forms with no live row (LF1-…
randomizedcoder Nov 3, 2026
8c0bc91
test(nlcap): kwlive workbench captures (LF2-T01)
randomizedcoder Nov 3, 2026
3f03f22
test(xtcpnl): O3 for the kwlive rows (LF2-T02)
randomizedcoder Nov 3, 2026
1332e18
test(goip): O5 over the kwlive rows (LF2-T03)
randomizedcoder Nov 3, 2026
04bb605
test(goipparity): kwlive matrix rows (LF3-T01)
randomizedcoder Nov 3, 2026
3f4b704
fix(nlparity): compare a nested attribute past its padding (LF3-T02)
randomizedcoder Nov 4, 2026
fee38a8
test(goipparity): gate the kwlive rows; close LF3 and the plan (LF3-T02)
randomizedcoder Nov 4, 2026
5599e47
Merge origin/main into goip-kinds/k0
randomizedcoder Nov 4, 2026
ee4bfca
docs(netlink): plan goip's lwt encap for routes, hops and nexthops
randomizedcoder Nov 4, 2026
45b51bf
feat(xtcpnl): encode lwt encap ip and ip6 with tunnel options (LE1-T01)
randomizedcoder Nov 4, 2026
62f0808
feat(goip): parse encap mpls, ip and ip6 in one lwtEncapArgs (LE1-T02)
randomizedcoder Nov 4, 2026
41e07d2
feat(goip): build a route's and a hop's lwt encap (LE2-T01)
randomizedcoder Nov 4, 2026
0dc0d9a
feat(goip): build a nexthop object's encap ip and ip6 (LE2-T02)
randomizedcoder Nov 4, 2026
b049bd1
feat(nlcapgen): the lwt family, 27 encap forms and 12 duplicates (LE3…
randomizedcoder Nov 4, 2026
e536f98
test(xtcpnl): capture the lwt rows twice; the first is the corpus (LE…
randomizedcoder Nov 4, 2026
6fc6a09
test(goip,xtcpnl): O3 and O5 over the lwt rows (LE3-T03)
randomizedcoder Nov 4, 2026
84260fe
test(goipparity,nlparity): lwt matrix rows; hops past padding (LE4-T01)
randomizedcoder Nov 4, 2026
ffc4491
test(goipparity): gate the lwt rows; close LE4 and the plan (LE4-T02)
randomizedcoder Nov 4, 2026
c2c8489
docs(netlink): plan goip's seg6, seg6local and the other encap types
randomizedcoder Nov 4, 2026
66d410e
feat(xtcpnl): encode seg6 and seg6local encaps (LX1-T01)
randomizedcoder Nov 4, 2026
d6e8ed2
feat(xtcpnl): encode ila, xfrm, ioam6 and rpl encaps (LX1-T02)
randomizedcoder Nov 4, 2026
a8ab98b
feat(goip): read seg6, seg6local, ila, xfrm, ioam6 and rpl (LX2-T01)
randomizedcoder Nov 4, 2026
43cf3cf
test(goip): the six encap types on a route, a hop and a nexthop (LX2-…
randomizedcoder Nov 4, 2026
fb6ab8a
feat(nlcapgen): the lwtx family, 56 encap forms and 17 duplicates (LX…
randomizedcoder Nov 4, 2026
e2037d9
test(xtcpnl): capture the lwtx rows twice; the first is the corpus (L…
randomizedcoder Nov 4, 2026
8f8eb65
test(goip,xtcpnl): O3 and O5 over the lwtx rows (LX3-T03)
randomizedcoder Nov 4, 2026
dfe50cf
test(goipparity): the lwtx matrix rows (LX4-T01)
randomizedcoder Nov 4, 2026
7a761fe
test(goipparity): gate the lwtx rows; close LX4 and the plan (LX4-T02)
randomizedcoder Nov 4, 2026
9394174
test(goip): next-csid's lblen value last; correct the hdrlen decision
randomizedcoder Nov 4, 2026
e74898b
docs(netlink): the segs cut is inside the route bound; ledger V030
randomizedcoder Nov 4, 2026
1e81c75
fix(goip): strcasecmp's ASCII fold for ll_proto names; strtoul's base…
randomizedcoder Nov 5, 2026
c02354f
fix(xtcp2): one secret-field list for the soft restart; bound and clo…
randomizedcoder Nov 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
1 change: 1 addition & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ linters:
# length fields) and io_uring batch indices; all are bounds-checked.
- G115
# G204: cmd/ns and cmd/nsTest spawn `ip netns exec ...`; required by design.
# cmd/xtcp2's soft restart execs os.Executable(), which no constant names.
- G204
# G304: register_schema reads .proto files whose path comes from CLI flags.
- G304
Expand Down
20 changes: 7 additions & 13 deletions cmd/ipfeed-collector/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,16 @@ import (
"time"
)

// setOrUnset sets key to val when set is true, otherwise ensures it is unset,
// registering cleanup so the surrounding environment is restored.
// setOrUnset sets key to val when set is true, otherwise ensures it is unset.
// t.Setenv records the surrounding value, set or not, and restores it at
// cleanup.
func setOrUnset(t *testing.T, key, val string, set bool) {
t.Helper()
prev, had := os.LookupEnv(key)
t.Cleanup(func() {
if had {
os.Setenv(key, prev) //nolint:errcheck,gosec // test env restore; failure is not actionable
} else {
os.Unsetenv(key) //nolint:errcheck,gosec // test env restore; failure is not actionable
t.Setenv(key, val)
if !set {
if err := os.Unsetenv(key); err != nil {
t.Fatalf("unset %s: %v", key, err)
}
})
if set {
os.Setenv(key, val) //nolint:errcheck,gosec // test env setup; failure is not actionable
} else {
os.Unsetenv(key) //nolint:errcheck,gosec // test env setup; failure is not actionable
}
}

Expand Down
169 changes: 169 additions & 0 deletions cmd/xtcp2/reexec_handoff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package main

import (
"errors"
"flag"
"fmt"
"io"
"os"
"strconv"

"github.com/randomizedcoder/xtcp2/gen/go/xtcp_config"
"github.com/randomizedcoder/xtcp2/pkg/xtcp"
"golang.org/x/sys/unix"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/proto"
)

// The soft restart's handoff to the image it execs into.
//
// - The config, its secrets blanked, goes in reconfigureEnvKey. The
// environment stays the readable record of what the daemon runs, so
// /proc/<pid>/environ shows the config but not the secrets, which the
// operator may have kept out of it with the *_FILE variables.
// - The secrets go in a sealed memfd, inherited across the exec, whose
// descriptor number is in reconfigureMemfdFDKey. It is anonymous
// memory: nothing on disk, and nothing in the environment but a number.
// - argv is rebuilt from the flags the command line set, not copied from
// os.Args, so it carries only flags this binary defines.

const (
// reconfigureMemfdFDKey names the descriptor that carries the
// config's secrets across the exec.
reconfigureMemfdFDKey = "XTCP_CONFIG_SECRETS_FD"
// reconfigureMemfdName is the memfd's name, as /proc/<pid>/fd shows it.
reconfigureMemfdName = "xtcp2-reconfigure-secrets"
// reconfigureSecretsMaxBytes bounds the read: six strings, the listener
// ones validated at 4 KiB each.
reconfigureSecretsMaxBytes = 1 << 20
// reconfigureSecretSeals are the seals the memfd carries: once written,
// its contents can't change and no seal can be removed.
reconfigureSecretSeals = unix.F_SEAL_SEAL | unix.F_SEAL_SHRINK | unix.F_SEAL_GROW | unix.F_SEAL_WRITE
)

var errReconfigureSecrets = errors.New("reconfigure secrets")

// splitSecrets returns cfg with its secrets blanked by ConfigService's
// xtcp.RedactSecrets, and a config holding only them. mergeSecrets is its
// inverse. TestSplitSecretsMatchesRedactSecrets fails if the fields carried
// here and the fields RedactSecrets blanks drift apart.
func splitSecrets(cfg *xtcp_config.XtcpConfig) (redacted, secrets *xtcp_config.XtcpConfig) {
redacted, ok := proto.Clone(cfg).(*xtcp_config.XtcpConfig)
if !ok {
redacted = &xtcp_config.XtcpConfig{}
}
xtcp.RedactSecrets(redacted)
secrets = &xtcp_config.XtcpConfig{
S3SecretKey: cfg.GetS3SecretKey(),
S3AccessKey: cfg.GetS3AccessKey(),
ListenerAuth: authSecrets(cfg.GetListenerAuth()),
AdminListenerAuth: authSecrets(cfg.GetAdminListenerAuth()),
}
return redacted, secrets
}

// authSecrets is a listener auth block's secrets alone; nil when it has none.
func authSecrets(a *xtcp_config.ListenerAuth) *xtcp_config.ListenerAuth {
if a.GetRawToken() == "" && a.GetHmacSharedKey() == "" {
return nil
}
return &xtcp_config.ListenerAuth{RawToken: a.GetRawToken(), HmacSharedKey: a.GetHmacSharedKey()}
}

// mergeSecrets puts splitSecrets' secrets back into its redacted config.
func mergeSecrets(cfg, secrets *xtcp_config.XtcpConfig) {
cfg.S3SecretKey = secrets.GetS3SecretKey()
cfg.S3AccessKey = secrets.GetS3AccessKey()
cfg.ListenerAuth = mergeAuthSecrets(cfg.ListenerAuth, secrets.GetListenerAuth())
cfg.AdminListenerAuth = mergeAuthSecrets(cfg.AdminListenerAuth, secrets.GetAdminListenerAuth())
}

func mergeAuthSecrets(a, s *xtcp_config.ListenerAuth) *xtcp_config.ListenerAuth {
if s == nil {
return a
}
if a == nil {
a = &xtcp_config.ListenerAuth{}
}
a.RawToken, a.HmacSharedKey = s.GetRawToken(), s.GetHmacSharedKey()
return a
}

// secretsMemfd writes b to a sealed memfd the exec'd image inherits: it is
// made without MFD_CLOEXEC, and syscall.Exec closes only close-on-exec
// descriptors. b past reconfigureSecretsMaxBytes is refused here, since
// the exec'd image would refuse it after this one is gone.
func secretsMemfd(b []byte) (f *os.File, fd int, err error) {
if len(b) > reconfigureSecretsMaxBytes {
return nil, -1, fmt.Errorf("%w: %d bytes, past %d", errReconfigureSecrets, len(b), reconfigureSecretsMaxBytes)
}
fd, err = unix.MemfdCreate(reconfigureMemfdName, unix.MFD_ALLOW_SEALING)
if err != nil {
return nil, -1, fmt.Errorf("%w: memfd_create: %w", errReconfigureSecrets, err)
}
f = os.NewFile(uintptr(fd), reconfigureMemfdName)
if _, err = f.Write(b); err == nil {
_, err = unix.FcntlInt(f.Fd(), unix.F_ADD_SEALS, reconfigureSecretSeals)
}
if err != nil {
return nil, -1, errors.Join(fmt.Errorf("%w: %w", errReconfigureSecrets, err), f.Close())
}
return f, fd, nil
}

// loadReconfigureSecrets reads the secrets a soft restart carried in a
// memfd into cfg, and closes it. It does nothing when the restart carried
// none. The descriptor must be a memfd with every seal secretsMemfd adds,
// so an inherited stdin or a stray file is refused rather than read; a
// memfd that is refused is closed too.
func loadReconfigureSecrets(cfg *xtcp_config.XtcpConfig) (err error) {
v, present := os.LookupEnv(reconfigureMemfdFDKey)
if !present || v == "" {
return nil
}
fd, err := strconv.ParseUint(v, 10, 31)
if err != nil || fd < 3 {
return fmt.Errorf("%w: %s=%q is not a descriptor", errReconfigureSecrets, reconfigureMemfdFDKey, v)
}
seals, err := unix.FcntlInt(uintptr(fd), unix.F_GET_SEALS, 0)
if err != nil {
return fmt.Errorf("%w: descriptor %d is not a memfd: %w", errReconfigureSecrets, fd, err)
}
// A memfd named by the key is the carry's, so it is closed from here
// on, read or refused.
f := os.NewFile(uintptr(fd), reconfigureMemfdName)
defer func() {
err = errors.Join(err, f.Close())
}()
if seals&reconfigureSecretSeals != reconfigureSecretSeals {
return fmt.Errorf("%w: descriptor %d is not sealed (seals %#x)", errReconfigureSecrets, fd, seals)
}
st, err := f.Stat()
if err != nil {
return fmt.Errorf("%w: %w", errReconfigureSecrets, err)
}
if st.Size() > reconfigureSecretsMaxBytes {
return fmt.Errorf("%w: %d bytes, past %d", errReconfigureSecrets, st.Size(), reconfigureSecretsMaxBytes)
}
b, err := io.ReadAll(io.NewSectionReader(f, 0, st.Size()))
if err != nil {
return fmt.Errorf("%w: %w", errReconfigureSecrets, err)
}
secrets := &xtcp_config.XtcpConfig{}
if err := protojson.Unmarshal(b, secrets); err != nil {
return fmt.Errorf("%w: %w", errReconfigureSecrets, err)
}
mergeSecrets(cfg, secrets)
return os.Unsetenv(reconfigureMemfdFDKey)
}

// reexecArgv is the soft restart's argv: exe, then each flag the command
// line set, as -name=value, in flag order. Every flag is a standard
// flag.Value, whose String parses back to the same value.
func reexecArgv(exe string, fs *flag.FlagSet) []string {
argv := []string{exe}
fs.Visit(func(f *flag.Flag) {
argv = append(argv, "-"+f.Name+"="+f.Value.String())
})
return argv
}
Loading
Loading