wgengine/magicsock: fix check for EPERM on macOS
Like Linux, macOS will reply to sendto(2) with EPERM if the firewall is currently blocking writes, though this behavior is like Linux undocumented. This is often caused by a faulting network extension or content filter from EDR software. Updates #11710 Updates #12891 Updates #13511 Signed-off-by: James Tucker <james@tailscale.com>
This commit is contained in:
parent
717d589149
commit
9eb59c72c1
|
@ -1149,8 +1149,8 @@ func (c *Conn) sendUDP(ipp netip.AddrPort, b []byte) (sent bool, err error) {
|
|||
// maybeRebindOnError performs a rebind and restun if the error is defined and
|
||||
// any conditionals are met.
|
||||
func (c *Conn) maybeRebindOnError(os string, err error) bool {
|
||||
switch err {
|
||||
case syscall.EPERM:
|
||||
switch {
|
||||
case errors.Is(err, syscall.EPERM):
|
||||
why := "operation-not-permitted-rebind"
|
||||
switch os {
|
||||
// We currently will only rebind and restun on a syscall.EPERM if it is experienced
|
||||
|
|
|
@ -2965,26 +2965,31 @@ func TestMaybeRebindOnError(t *testing.T) {
|
|||
tstest.PanicOnLog()
|
||||
tstest.ResourceCheck(t)
|
||||
|
||||
conn := newTestConn(t)
|
||||
defer conn.Close()
|
||||
err := fmt.Errorf("outer err: %w", syscall.EPERM)
|
||||
|
||||
t.Run("darwin-rebind", func(t *testing.T) {
|
||||
rebound := conn.maybeRebindOnError("darwin", syscall.EPERM)
|
||||
conn := newTestConn(t)
|
||||
defer conn.Close()
|
||||
rebound := conn.maybeRebindOnError("darwin", err)
|
||||
if !rebound {
|
||||
t.Errorf("darwin should rebind on syscall.EPERM")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("linux-not-rebind", func(t *testing.T) {
|
||||
rebound := conn.maybeRebindOnError("linux", syscall.EPERM)
|
||||
conn := newTestConn(t)
|
||||
defer conn.Close()
|
||||
rebound := conn.maybeRebindOnError("linux", err)
|
||||
if rebound {
|
||||
t.Errorf("linux should not rebind on syscall.EPERM")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("no-frequent-rebind", func(t *testing.T) {
|
||||
conn := newTestConn(t)
|
||||
defer conn.Close()
|
||||
conn.lastEPERMRebind.Store(time.Now().Add(-1 * time.Second))
|
||||
rebound := conn.maybeRebindOnError("darwin", syscall.EPERM)
|
||||
rebound := conn.maybeRebindOnError("darwin", err)
|
||||
if rebound {
|
||||
t.Errorf("darwin should not rebind on syscall.EPERM within 5 seconds of last")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue