Skip to content

Commit 90423bf

Browse files
committed
wgengine/netstack: make userspace ping work when tailscaled has CAP_NET_RAW
Updates tailscale#3710 Change-Id: Ief56c7ac20f5f09a2f940a1906b9efbf1b0d6932 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com> (cherry picked from commit a93937a)
1 parent 0028a8d commit 90423bf

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

wgengine/netstack/netstack.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"tailscale.com/syncs"
4242
"tailscale.com/types/logger"
4343
"tailscale.com/types/netmap"
44+
"tailscale.com/version/distro"
4445
"tailscale.com/wgengine"
4546
"tailscale.com/wgengine/filter"
4647
"tailscale.com/wgengine/magicsock"
@@ -394,8 +395,14 @@ func (ns *Impl) shouldProcessInbound(p *packet.Parsed, t *tstun.Wrapper) bool {
394395
return false
395396
}
396397

398+
// setAmbientCapsRaw is non-nil on Linux for Synology, to run ping with
399+
// CAP_NET_RAW from tailscaled's binary.
400+
var setAmbientCapsRaw func(*exec.Cmd)
401+
397402
var userPingSem = syncs.NewSemaphore(20) // 20 child ping processes at once
398403

404+
var isSynology = runtime.GOOS == "linux" && distro.Get() == distro.Synology
405+
399406
// userPing tried to ping dstIP and if it succeeds, injects pingResPkt
400407
// into the tundev.
401408
//
@@ -426,11 +433,21 @@ func (ns *Impl) userPing(dstIP netaddr.IP, pingResPkt []byte) {
426433
}
427434
err = exec.Command(ping, "-c", "1", "-w", "3", dstIP.String()).Run()
428435
default:
429-
err = exec.Command("ping", "-c", "1", "-W", "3", dstIP.String()).Run()
436+
ping := "ping"
437+
if isSynology {
438+
ping = "/bin/ping"
439+
}
440+
cmd := exec.Command(ping, "-c", "1", "-W", "3", dstIP.String())
441+
if isSynology && os.Getuid() != 0 {
442+
// On DSM7 we run as non-root and need to pass
443+
// CAP_NET_RAW if our binary has it.
444+
setAmbientCapsRaw(cmd)
445+
}
446+
err = cmd.Run()
430447
}
431448
d := time.Since(t0)
432449
if err != nil {
433-
ns.logf("exec ping of %v failed in %v", dstIP, d)
450+
ns.logf("exec ping of %v failed in %v: %v", dstIP, d, err)
434451
return
435452
}
436453
if debugNetstack {

wgengine/netstack/netstack_linux.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright (c) 2021 Tailscale Inc & AUTHORS All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package netstack
6+
7+
import (
8+
"os/exec"
9+
"syscall"
10+
11+
"golang.org/x/sys/unix"
12+
)
13+
14+
func init() {
15+
setAmbientCapsRaw = func(cmd *exec.Cmd) {
16+
cmd.SysProcAttr = &syscall.SysProcAttr{
17+
AmbientCaps: []uintptr{unix.CAP_NET_RAW},
18+
}
19+
}
20+
}

0 commit comments

Comments
 (0)