portlist: avoid syscall audit violation logspam on Android

If we don't have access, don't try, don't log, don't continue trying.

Fixes #521
This commit is contained in:
Brad Fitzpatrick 2020-07-28 13:17:38 -07:00
parent 84f2320972
commit 77cad13c70

View File

@ -10,12 +10,15 @@
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"runtime"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
"tailscale.com/syncs"
) )
// Reading the sockfiles on Linux is very fast, so we can do it often. // Reading the sockfiles on Linux is very fast, so we can do it often.
@ -26,13 +29,30 @@
var sockfiles = []string{"/proc/net/tcp", "/proc/net/udp"} var sockfiles = []string{"/proc/net/tcp", "/proc/net/udp"}
var protos = []string{"tcp", "udp"} var protos = []string{"tcp", "udp"}
var sawProcNetPermissionErr syncs.AtomicBool
func listPorts() (List, error) { func listPorts() (List, error) {
if sawProcNetPermissionErr.Get() {
return nil, nil
}
l := []Port{} l := []Port{}
for pi, fname := range sockfiles { for pi, fname := range sockfiles {
proto := protos[pi] proto := protos[pi]
// Android 10+ doesn't allow access to this anymore.
// https://developer.android.com/about/versions/10/privacy/changes#proc-net-filesystem
// Ignore it rather than have the system log about our violation.
if runtime.GOOS == "android" && syscall.Access(fname, unix.R_OK) != nil {
sawProcNetPermissionErr.Set(true)
return nil, nil
}
f, err := os.Open(fname) f, err := os.Open(fname)
if os.IsPermission(err) {
sawProcNetPermissionErr.Set(true)
return nil, nil
}
if err != nil { if err != nil {
return nil, fmt.Errorf("%s: %s", fname, err) return nil, fmt.Errorf("%s: %s", fname, err)
} }
@ -96,7 +116,18 @@ func addProcesses(pl []Port) ([]Port, error) {
} }
err := foreachPID(func(pid string) error { err := foreachPID(func(pid string) error {
fdDir, err := os.Open(fmt.Sprintf("/proc/%s/fd", pid)) fdPath := fmt.Sprintf("/proc/%s/fd", pid)
// Android logs a bunch of audit violations in logcat
// if we try to open things we don't have access
// to. So on Android only, ask if we have permission
// rather than just trying it to determine whether we
// have permission.
if runtime.GOOS == "android" && syscall.Access(fdPath, unix.R_OK) != nil {
return nil
}
fdDir, err := os.Open(fdPath)
if err != nil { if err != nil {
// Can't open fd list for this pid. Maybe // Can't open fd list for this pid. Maybe
// don't have access. Ignore it. // don't have access. Ignore it.