portmapper.go was introduced for UPnP in commit
8ed43f1f2a.
This also adds a unit test which exercises the incomplete
natlab server implementation of these portmapping protocols.
Updates #21713
Change-Id: I33b61ccbe8c1d8d99d56aa357ae24777be3f5739
Signed-off-by: Francois Marier <francois@tailscale.com>
This test encodes the current behaviour of the Tailscale client.
It only covers the creation of new mappings.
Updates #21713
Change-Id: Ia44877036569660f4129484d5059ed22ffbf9cda
Signed-off-by: Francois Marier <francois@tailscale.com>
Resolve Server.Dial and Server.HTTPClient names using the tailnet's DNS
configuration, including MagicDNS, search domains, split DNS routes, and
global resolvers. Preserve the dialer's local MagicDNS fast path.
Add Server.LookupIP for direct lookups returning netip.Addr values. Keep
the resolver implementation private to tsnet. Search expansion uses
ndots=1, includes the MagicDNS suffix when enabled, and respects trailing
dots. Each lookup uses the current DNS configuration.
Use the internal resolver before considering host fallback. Configured
upstream failures and authoritative local denials must not fall back to
the host resolver; the host's hosts file is consulted only during fallback.
Distinguish configured routes from ambient cloud-host fallback resolvers.
Cover search expansion, split and global DNS, MagicDNS-disabled operation,
configuration updates, hosts-file precedence, and dialing in tests.
Fixes#5840
Updates #7984
Updates #15260
Updates #4677
Change-Id: I832bc4c68658d2d25c5dc29b79acf611fc11e59e
Signed-off-by: James Tucker <james@tailscale.com>
This bare-bones implementation of a UPnP server covers only what
the Tailscale client needs in order to successfully create a
new mapping.
A new flag is introduced for the test control server so that UPnP
can continue to be disabled in all tests except natlab.
Updates #21713
Change-Id: I57779e07c6a628a12bb30dccabd94f7bb21270c4
Signed-off-by: Francois Marier <francois@tailscale.com>
Add experimental tool for generating a matrix of tests to be run by CI.
This tool will parse the test files in the vmtest folder, and find
candidates that can be with with a set of variations. For now that is
expressed as different flavours of Linux, but it can be expanded across
OS'es but also other things like NAT configurations and portmapper
extensions available.
Updates #21817
Signed-off-by: Claus Lensbøl <claus@tailscale.com>
Explicitly close the other end of the losing connection.
This is a follow-up to 31baee90c0.
Updates #cleanup
Change-Id: I5bf36a7451da05545e7242ee5c1bff02fa44b362
Signed-off-by: Francois Marier <francois@tailscale.com>
When receiving a PCP request, a NAT-PMP-only server must reply with
an unsupported version response. Same for a PCP-only server
receiving a NAT-PMP request.
The tailscale client sends both a NAT-PMP and a PCP request when
probing for portmapping support and it correctly handle any
unsupported version response it receives.
Updates #21713
Change-Id: I0ec8b4a6c1de14bcc64b82f1988cde7fc01f5747
Signed-off-by: Francois Marier <francois@tailscale.com>
Adds tests that only a 404 map response wraps ErrNodeRemoved, that the
node-removed warning and NeedsLogin state are cleared by a new netmap or
a profile switch, and that a node restarted after it was deleted shows
the warning and reaches NeedsLogin.
Updates #18700
Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
When validation fails, WaitOrder returns only the order's status, so
tailscale cert printed "acme: order ... status: invalid" with no reason.
The CA's reason is on the authorization's challenge. Wait on each
authorization before the order and return that error instead.
To test this, move natlab's fake ACME CA to tstest/acmetest, where unit
tests can import it, and teach it tls-alpn-01, a validation hook, and
the "invalid" state a CA reports when validation fails.
Updates #21759
Signed-off-by: Brendan Creane <bcreane@gmail.com>
This implements enough of PCP to establish direct connections
with a node behind a hard NAT.
Updates #21713
Change-Id: I44b955e9b8ecce80ddc49afdfb01eb49c8d56f8c
Signed-off-by: Francois Marier <francois@tailscale.com>
Since 7e609b258 (v1.102), quad-100 looks up MagicDNS names in
nodeBackend.nodeByName, which also holds short-name keys for in-process
dials. So a query for "foo." matched peer "foo.tail-scale.ts.net" and
was answered with its Tailscale IP. 1ec348784 fixed that for MagicDNS
off; this fixes it for MagicDNS on, too, matching pre-1.102 behavior.
The OS applies the search domain to short names before they reach
quad-100, so a single-label query is a root zone name, not a tailnet
name, and must be forwarded (e.g. to LAN mDNS/LLMNR or a global
nameserver). Short names still work for in-process dials via
NodeByName.
Updates #20789
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Ic8199a96cf79178210c9a85e0cebfb46567a894a
This will make the addition of PCP support easier.
No changes to NAT-PMP support or tests.
Updates #21713
Change-Id: I7ac58badbd4e8680c0e50d8dd5d78d6d0abb4aa0
Signed-off-by: Francois Marier <francois@tailscale.com>
To faciliate roaming a few things had to happen as tta communicated over
the same links as tailscaled communicates over, meaning that the
connection to tta gets cut when cutting the interface.
- Whenever we have connected to the client after waiting for it to come
up, clean up idle connections.
- Have tta use keepalives to reconnect.
- Delete default route on just via, not the interface.
- Add capabilities to QMP for setting the interface state.
- Implement the test.
Fixestailscale/corp#49639
Signed-off-by: Claus Lensbøl <claus@tailscale.com>
ImportAliasCheck runs git grep in a subprocess, whose file reads Go's
test cache can't see. With a shared CI test cache, callers' tests kept
reporting a stale "ok (cached)" for new commits that added bad
x/exp/{maps,slices} imports, as long as the test binary didn't change.
That's how tailscale/corp#49716 merged with green CI.
Read GITHUB_SHA so Go records it in the test cache key, making the
cached result per-commit in CI.
Updates tailscale/corp#49716
Change-Id: I6301f5ed067a05294185b05a195550efa8e5aa01
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
On hosts without hardware virtualization, gokrazy VMs can hang at
boot with no console output. Timing jitter under software emulation
breaks the kernel's early boot timer calibration, causing it to spin
waiting for timer interrupts that never arrive.
Passing -icount shift=auto ties virtual clocks to instruction execution,
making timer calibration deterministic and preventing the boot hang.
Updates #cleanup
Change-Id: I7c0aa96e5344041af9a7246f7d50bed1da47ab95
Signed-off-by: Francois Marier <francois@tailscale.com>
WithDHCPClient(DHCPClientDhcpcd) makes systemd-networkd leave the vnet NIC
unmanaged and runs the dhcpcd that the Ubuntu 24.04 image ships on it.
dhcpcd is the DHCP client on Raspberry Pi OS and other distributions, and
unlike networkd it configures the interface first and runs its resolvconf
hook afterwards. TestDhcpcdOpenresolvDNS checks that dhcpcd holds the
lease, its hook registered the lease's nameserver with openresolv, and
tailscaled forwards through it.
Updates #21607
Signed-off-by: Brendan Creane <bcreane@gmail.com>
A TCP retry to the server that just answered can only return the same
rcode, and when that server accepted the connection and never answered,
the query ran the full 10s dnsQueryTimeout and the client got nothing.
An upstream rcode now ends the UDP/TCP race when it arrives, and the
client gets it once every resolver has had udpRaceTimeout to answer
instead of waiting for all of them to report. tcpQueryTimeout is also
set on the conn, since a context cannot interrupt a blocked read, and a
new dns_query_fwd_udp_read_ctx_done counter separates query teardown
from upstream read errors.
Fixes#20826
Signed-off-by: Brendan Creane <bcreane@gmail.com>
While a VM reboots, tests poll its agent roughly every 5s. Each
request that times out leaves behind a goroutine blocked in
Server.takeAgentConn, waiting for TTA to connect back. Several can
pile up before a request succeeds and the test ends, and the rest
wait forever.
Making takeAgentConn return at Server shutdown unblocks any goroutine
still waiting when the test ends.
In a full vmtest run, the two dials stranded by the reboot in
TestGokrazyUpdatesItselfToSameImage logged until the package exited
10 minutes later. With this change, "still waiting" log lines in the
same run drop from 267 to 72, and the longest wait goes from 10m10s
to 40s.
Updates #cleanup
Change-Id: Ib4c1d2ce8f2a7b73d3f0c1e6a9e5b2d8f4a1c7e3
Signed-off-by: Francois Marier <francois@tailscale.com>
Only gokrazy builds trust the fake log catcher's TLS certificate, so
Ubuntu, Debian, Fedora and FreeBSD guests failed every upload and the
failure dump of their tailscaled logs was always empty. vnet now also
serves the log catcher over plain HTTP on port 80, and the harness points
those guests at it with TS_LOG_TARGET. Env.NodeLogs returns what a node
has uploaded.
macOS guests still do not upload: tailmac does not pass TailscaledEnv to
tailscaled, so the setting would not reach it.
Updates #13038
Signed-off-by: Brendan Creane <bcreane@gmail.com>
TestSelfSignedDERPHashPinning occasionally fails on a slow vm with:
tailscale up (limit 1m30s): Get "http://unused/up?accept-routes=true": EOF
Because this endpoint has both IPv4 and IPv6 addresses, TTA will fall
back to the second address when running on a slow host and race both
connections. The losing connection will get closed by net.Dialer and
never produce a response.
By keeping the gVisor endpoint with the conn, we can avoid returning
closed connections in takeAgentConnOne().
This fix uncovered a bug in Env.Tailscale(): calling "tailscale
update" via a GET request may be replayed by net.http.Transport and
that will trigger a second update undoing the first. Using POST
disables all such retries.
Update #cleanup
Change-Id: I2f8b7c4d9e1a3b5c7d0e2f4a6b8c1d3e5f7a9b0c
Signed-off-by: Francois Marier <francois@tailscale.com>
The NL prefix is one of the last references to the "Network Lock" name
which we're cleaning up.
Updates tailscale/corp#37904
Change-Id: I751194e0b49447e97a65ed6975e3da680226ce85
Signed-off-by: Alex Chan <alexc@tailscale.com>
The agent and tailscaled are started concurrently by gokrazy and
tta can win that race, in which case it answers 502 Bad Gateway
because tailscaled.sock does not exist yet.
This is most likely to be seen on slower machines using TCG.
Updates #cleanup
Change-Id: I4012bd189adfb2565470c814204fcf18545f1017
Signed-off-by: Francois Marier <francois@tailscale.com>
Add vmtests that boot pairs of gokrazy VMs whose tailscale and tailscaled
are minimal builds and check that IP traffic flows between them over
WireGuard, so we notice if a minimal build stops doing its one job:
build_dist.sh --extra-small (direct path through NATs), that minus NAT
traversal (DERP across NATs, direct on a shared LAN), and DERP-only.
They found that "tailscale up" built with ts_omit_ipnbus returned before
calling Start or EditPrefs, making it a no-op. Fix that, and have it wait
for the Running state by polling tailscaled's status instead of watching
the IPN bus, so scripts can rely on it as with normal builds.
The extra-small feature list moves to featuretags.ExtraSmall so
build_dist.sh (via a new "featuretags --extra-small") and vmtest share
it. The gokrazy builder gains --output and --go-build-tags flags to build
the variant images, and natlabprep --gokrazy prebuilds them all for CI.
Updates #13038
Updates #12614
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I0caa2c7b3adf2399da09b6d07a942f1dc34e8486
There were a handful of inconsitencies in natlab with the biggest being.
- Pair and grid tests living under tstest/integration and using the old
test style.
- Inconsistent use of e vs env.
- Methods for actions on node living on the vnet.Node rather than being
a method on vmtest.Env
Clean up these inconsitencies.
Updates #cleanup
Signed-off-by: Claus Lensbøl <claus@tailscale.com>
It's possible for multiple direct connections to be counted and
these tests are successful as long as it's more than one.
Fixes#21578
Change-Id: I979efc92a43f78d0e51d602d96e61828e6fabdff
Signed-off-by: Francois Marier <francois@tailscale.com>
Select the published reco-backed test server with a build tag while
preserving the default implementation and existing caller API. Pin the
public module with its proxy-verified checksums; no workspace is needed.
Accept incremental peer messages in the TSP test. Exercise legacy map
semantics with the default server and version-floor rejection with reco,
including current-version streaming, without manual test skips.
Document GOFLAGS usage so child Go builds inherit the experiment tag.
Updates tailscale/corp#49097
Change-Id: I9b3e086c4c6a9a57a076e76b883422875c843f20
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
A peer removal sent with any MapResponse field that forces a full netmap
rebuild never reaches IPN bus watchers; these tests fail.
Updates #15660
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This adds a tailscaled string flag "--windows-mode" which accepts two
possible values: the empty string (default) to get the normal behavior
(tailscaled running as an admin, usually as a service), and "dev", to
make the safesocket named pipe path be at a location that regular
users (non-admins) can create.
It then modifies the safesocket client side (as used by the CLI) to
try the dev mode path too on failure.
This lets people work on tailscaled.exe+tailscale.exe in a terminal
easily during development, as either an admin or non-admin. (This
used to work prior to the move away from TCP localhost to named pipes
for safesocket on Windows)
Updates #2791
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I9c1e3a5b7d0f2a4c6e8b0d2f4a6c8e0b2d4f6a8c
On backends that can't do OS-level split DNS, Tailscale forwards the default
route to the system's own resolvers, which it reads out of the OS config. At
boot that config may not be populated yet, because NetworkManager or
systemd-resolved haven't run, and Tailscale took over regardless: it pointed
the OS at 100.100.100.100 but compiled an empty "." route, so every
non-Tailscale name failed to resolve for the rest of the process's life.
Fail compileConfig instead, which leaves the OS resolvers in place, and
retry the last config with a bounded backoff until resolvers appear. A
health warning explains why MagicDNS is inactive in the meantime.
Sandboxed macOS and iOS are exempt. There the network extension reapplies
the config itself when the OS nameservers change, and quad-100 as the
primary resolver is what keeps tailnet names resolving while the base config
is still empty. Dropping the exemption is tracked in tailscale/corp#48962.
This also changes the outcome on an openresolv host with no snippets
registered. Since the fix for #20825, openresolv reports an empty base config
there and tailscaled took over with no upstream, so every public name got
SERVFAIL. Such a host now keeps its resolv.conf and shows the health warning
instead. TestOpenresolvDNS checks that outcome.
TestSplitDNSEmptyBaseConfig covers the boot race end to end in natlab: it
empties resolv.conf on a guest using the "direct" backend, checks that
tailscaled leaves it alone, then adds a resolver and checks that both tailnet
and public names resolve.
Fixes#20341
Signed-off-by: Brendan Creane <bcreane@gmail.com>
FreeBSD handles subnet routes in netstack by default, but the router
still installed its pf NAT rules whenever SNATSubnetRoutes was set,
which is the default. Every FreeBSD node, subnet router or not, loaded
and enabled pf, inserted anchor references into the host's main
ruleset and loaded NAT rules that netstack never needed, since
netstack dials subnet destinations from the host's own addresses.
It also flipped the forwarding sysctls for any advertised route.
Only do either when the kernel path is opted into with
TS_DEBUG_NETSTACK_SUBNETS=false and routes are advertised.
TestSubnetRouterFreeBSDManyFlows ran in netstack mode since the default
changed, so it no longer exercised pf at all. Opt it into the kernel
path and assert the anchor holds NAT rules, and have
TestSubnetRouterFreeBSD assert the default mode leaves pf untouched.
Also drop the stale claim in handleSubnetsInNetstack that the pf NAT
rule never matches; that was the (self) pool bug, since fixed.
Updates #21450
Change-Id: Ibf91a676a026cebb29f64e39a64fe8e75488360b
Signed-off-by: Martin Minkus <martin.minkus@sonic.com>
FreeBSD is a weak-host stack like Linux, so a LAN-adjacent machine can
send a SYN for a node's Tailscale IP to the node's NIC and get the
kernel's SYN-ACK from the peerapi port, confirming which tailnet
identity that MAC address belongs to. Linux closes this with
SO_BINDTODEVICE and macOS/iOS with IP_BOUND_IF, but FreeBSD has no
per-socket interface bind (only IP_RECVIF and SO_SETFIB).
Instead, treat FreeBSD like Android: when netstack is present, don't
create a kernel-level peerapi listener at all and use the fake listener,
since netstack already intercepts peerapi connections from peers in
userspace and the kernel socket only ever served the local host. When
netstack is compiled out (ts_omit_netstack), the kernel listener is the
only way to serve peers, so keep it and log that it must be restricted
with pf.
Along the way, tailscaled's own pf source NAT rule on FreeBSD turned out
to rewrite the source of such a SYN-ACK to the LAN IP and a random port,
so a plain connect() from the LAN never completes. The SYN-ACK still
leaks, though, so the natlab test now watches for SYN-ACKs on the
attacker's NIC with tcpdump instead of checking for a completed
handshake, and gains a FreeBSD variant. With the fix disabled, that
variant fails on the leaked SYN-ACK from the peerapi port.
Fixes#21419
Updates tailscale/corp#48248
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I0d2de4ebc9bae28450d500bd7b6ddbfa70f9052f
There are two copies of the read file descriptor (parent & child).
Since the parent copy is unused, we can close it after fork.
Updates #cleanup
Change-Id: Id789e0a04970c9fb8eaeed1f299aa25f29fcf48c
Signed-off-by: Francois Marier <francois@tailscale.com>
In my testing using TCG, I hit non-EOF network errors that made
this test fail. Since we already poll and check the image version
later, we can treat this response as best-effort.
Resolves#21440
Change-Id: Ia923fc2c199aae7a543d00e06d25a375512daa01
Signed-off-by: Francois Marier <francois@tailscale.com>
Linux is a weak-host stack, so a LAN-adjacent machine can complete a
TCP handshake with a node's peerapi listener by sending a packet to
the node's Tailscale IP, with no credentials and no tailnet
membership.
macOS and iOS already bind the listener to the tunnel interface, and
Windows is protected by its strong host model, so Linux tun mode was
the only platform that leaked.
Bind the Linux listener to the tunnel interface as well, so the
kernel only answers connections that arrive from the tunnel or from
the local host. A natlab VM test verifies that a same-LAN machine can
no longer complete the handshake, while local and peer peerapi keep
working.
FreeBSD has the same weak-host exposure but no per-socket equivalent,
so handling it there with pf is a TODO (#21419).
Updates tailscale/corp#48248
Reported-By: Samuel Keeley (@keeleysam)
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I5f8501b0938c9f7aa39c4c12ebddd988c72e89bf
When a natlab node's "tailscale up" hung (TestEasyEasy on CI, twice on
main), the only bound was the 10 minute test context, so the failure
arrived as go test's timeout panic. The VM console logs weren't dumped
(t.Cleanup doesn't run on a panic), and they wouldn't have helped
anyway: on gokrazy the console holds only kernel and init output, while
tailscaled's stdout/stderr goes to a remote syslog that vnet discards
unless the node has VerboseSyslog set. There was no way to see what the
stuck node was doing.
Bound each node's "tailscale up" in Env.Start to 90 seconds (it takes
about a second against the in-process control server), so a stuck node
becomes a normal test failure. On failure, dump the tail of each node's
tailscaled logs from vnet's fake log.tailscale.com log catcher, which
already buffered them per node but exposed them to nothing; add
Server.NodeLogs for that. Also add VMTEST_VERBOSE_SYSLOG=1 to stream
the guests' syslog into the test output live, the vmtest equivalent of
tstest/integration/nat's --log-tailscaled flag.
With this, the CI hang reproduced locally under CPU pressure (2 CPUs
shared with busy loops) in 1 of 22 runs, and the dumped logs showed
tailscaled's control client stuck at "awaiting unpause", which is fixed
separately.
Updates #deflake
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: Icfd3a2cdc66d924388a722f3a3cd19f86e116921
The Windows GitHub runners' provisioning daemon, provjobd.exe, opens a
handle to each freshly-written tailscaled.exe. tb.TempDir's own cleanup
retries for a fixed 2s and gives up, failing whichever test happens to tear
down while the handle is held.
Updates #21099
Signed-off-by: Yaruk Asghar <yaruk@tailscale.com>
TestNATPing called SetMasqueradeAddresses on the test control server
and then immediately read both nodes' status, expecting the new
masqueraded peer addresses to already be there. But the change reaches
the nodes asynchronously via their streaming map responses, so under
load the status check ran before the new map response arrived and the
test failed with "n1 sees n2 as 100.64.0.2; want 100.64.2.1" and the
like. This was the dominant failure mode on the flakes dashboard (11 of
the 18 most recent CI failures) and the only one found in a six hour
Antithesis run (run 30b4de27d89d8d7a651e7b43b3f1ec3f-61-9, 54 failures
in 16,599 runs).
Wait for each node's status to report the expected peer address
instead. Also retry the "tailscale ping" invocations, since a ping can
fail transiently right after a map response changes a peer's addresses
and before the engine is reconfigured; the second most common failure
mode was pings exiting with status 1. Failed pings now include the CLI
output in the error rather than a bare exit status.
Locally, flakestress (32 workers) reproduced the failure in 29 of 210
runs before this change (13.8%) and in 0 of 1,173 runs after.
The remaining Windows-only failure mode on the dashboard, TempDir
cleanup failing because tailscaled.exe is still open, is a
harness-wide issue that affects every integration test and is not
specific to this test.
Fixes#12169
Updates tailscale/corp#47865
Change-Id: I7c3e2b8a5d914f0e6a2b1c9d8e7f6a5b4c3d2e1f
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Update gVisor to include its fix for RACK loss detection with coarse
monotonic clocks. Configure netstack with the 500 microsecond clock
resolution used on Windows so RACK accounts for timestamp quantization.
Remove the TCP recovery override that disabled RACK, enabling gVisor's
default RACK behavior on all platforms.
Switch netstack to cubic congestion control. The int overflow in CUBIC
sender cwnd arithmetic that required pinning reno has since been reworked
upstream into float arithmetic with RFC 9438 target clamping.
Align the natlab vnet stack with netstack: enable cubic, and drop the
now-redundant explicit SACK and receive-buffer moderation sets, both of
which are gVisor defaults.
Fixes#9707
Signed-off-by: James Tucker <jftucker@gmail.com>
TestOpenresolvDNS pins the case where Tailscale owns the only resolvconf
snippet, so on its own it would also pass if tailscaled never read an OS
base config at all. Register a snippet the way a DHCP client would, then
toggle accept-dns to force a reapply, and assert its nameserver becomes
quad-100's upstream.
SetAcceptDNS is the toggle: tailscaled has no reason to re-read the OS
config on its own, and this avoids rebooting the guest to change what the
OS resolver looks like mid-test.
Updates #20825
Updates tailscale/corp#44793
Signed-off-by: Brendan Creane <bcreane@gmail.com>
wintun-go loads wintun.dll only from the application directory and
System32. The MSI puts it there, but a plain "go build" tailscaled.exe run
from a terminal has no wintun.dll, and tstunNewWithWindowsRetries then
retried tstun.New for five minutes with nothing in the log but
tstunNew: backoff: 13 msec
tstunNew: backoff: 32 msec
because backoff.BackOff never logs the error it's given, and after the
timeout the function returned context.DeadlineExceeded, discarding the
real error.
Instead, log with helpful text if we detect that.
Updates #21290
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Change-Id: I09dca3317974a977deb9956657a7e36e9ec8c572
Tests that exec a fresh CopyTo copy of the tailscale/tailscaled
binaries occasionally failed with "text file busy" on GitHub
Actions, previously worked around with the retry loop in
awaitTailscaledRunnable.
The root cause: CopyTo's Linux hardlink fast path only works while
the built binary is still linked somewhere. The kernel refuses to
hardlink an inode whose link count is zero, even via the still-open
FD, so once the building test's TempDir (and every other test's copy)
has been cleaned up, later tests silently fall through to the
byte-copy path. That path writes the new copy from the test process
itself, and if another parallel test forks a child while the write FD
is open, the child holds the inherited FD (O_CLOEXEC only closes at
exec, not at fork) and a subsequent exec of the fresh copy fails with
ETXTBSY. This is golang.org/issue/22315. On macOS and the BSDs,
CopyTo always takes the byte-copy path, so every copy races there.
Fix it the way the syscall package documents: hold ForkLock for
reading across the copy so that no fork overlaps the lifetime of the
write FD. A standalone stress program reproduced the race in 86 of
200 execs under a fork storm and in 0 of 200 with the lock held.
Updates #15868
Updates #15865
Change-Id: I8a6be72826c9073a9187d7e6c90c8733d2dadb05
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Previously retry-after support was added to register requests in #19403,
in order to have more fine tuned client/control interactions in cases of
rate limiting.
This change expands that support to map sessions as well.
Updates tailscale/corp#47299
Signed-off-by: Evan Lowry <evan@tailscale.com>
* net/dns: export OSConfigurationReadWarnable
A natlab vmtest checks that a node is not reporting this warning. Exporting
the Warnable lets the test take the warning's text from it, instead of
keeping a copy of the wording that could stop matching without failing.
Updates #20825
Updates tailscale/corp#44793
Signed-off-by: Brendan Creane <bcreane@gmail.com>
* tstest/natlab/vmtest: add VM coverage for the openresolv DNS backend
dnsMode() picks one of five Linux DNS backends, and natlab could provision
only systemd-resolved and direct. Add a DNSOpenresolv mode and a VM test for
it, so the backend behind #20825 is covered.
No cloud image ships openresolv and a guest cannot download it, so its two
source files are vendored under testdata and installed with cloud-init's
write_files. openresolv's build is a set of sed substitutions with nothing to
compile, so resolvconf.go does the substitutions in process.
Updates #20825
Updates tailscale/corp#44793
Signed-off-by: Brendan Creane <bcreane@gmail.com>
---------
Signed-off-by: Brendan Creane <bcreane@gmail.com>