From d67b1e8a64f86ded2e7edf7c5ce84c971bf1f000 Mon Sep 17 00:00:00 2001 From: Daniel Date: Mon, 18 Dec 2023 17:03:48 +0100 Subject: [PATCH] Reduce PID finding retries and simply proc interface on linux --- network/proc/findpid.go | 65 +++++++-------------------------- network/state/lookup.go | 5 +++ network/state/system_default.go | 5 --- network/state/system_linux.go | 14 +++---- network/state/system_windows.go | 7 ---- 5 files changed, 24 insertions(+), 72 deletions(-) diff --git a/network/proc/findpid.go b/network/proc/findpid.go index 657e8524a..2fbb71304 100644 --- a/network/proc/findpid.go +++ b/network/proc/findpid.go @@ -7,17 +7,11 @@ import ( "io/fs" "os" "strconv" - "time" "github.com/safing/portbase/log" "github.com/safing/portmaster/network/socket" ) -var ( - baseWaitTime = 3 * time.Millisecond - lookupRetries = 3 -) - // GetPID returns the already existing pid of the given socket info or searches for it. // This also acts as a getter for socket.Info.PID, as locking for that occurs here. func GetPID(socketInfo socket.Info) (pid int) { @@ -43,60 +37,27 @@ func GetPID(socketInfo socket.Info) (pid int) { func findPID(uid, inode int) (pid int) { socketName := "socket:[" + strconv.Itoa(inode) + "]" - for i := 0; i <= lookupRetries; i++ { - var pidsUpdated bool - - // Get all pids for the given uid. - pids, ok := getPidsByUser(uid) - if !ok { - // If we cannot find the uid in the map, update it. - updatePids() - pidsUpdated = true - pids, ok = getPidsByUser(uid) - } + // Always update pid table (it has a call limiter anyway) + updatePids() - // If we have found PIDs, search them. - if ok { - // Look through the PIDs in reverse order, because higher/newer PIDs will be more likely to - // be searched for. - for i := len(pids) - 1; i >= 0; i-- { - if findSocketFromPid(pids[i], socketName) { - return pids[i] - } - } - } - - // If we still cannot find our socket, and haven't yet updated the PID map, - // do this and then check again immediately. - if !pidsUpdated { - updatePids() - pids, ok = getPidsByUser(uid) - if ok { - // Look through the PIDs in reverse order, because higher/newer PIDs will be more likely to - // be searched for. - for i := len(pids) - 1; i >= 0; i-- { - if findSocketFromPid(pids[i], socketName) { - return pids[i] - } - } - } - } - - // We have updated the PID map, but still cannot find anything. - // So, there is nothing we can do other than to wait a little for the kernel to - // populate the information. + // Get all pids for the given uid. + pids, ok := getPidsByUser(uid) + if !ok { + return socket.UndefinedProcessID + } - // Wait after each try, except for the last iteration - if i < lookupRetries { - // Wait in back-off fashion - with 3ms baseWaitTime: 3, 6, 9 - 18ms in total. - time.Sleep(time.Duration(i+1) * baseWaitTime) + // Look through the PIDs in reverse order, because higher/newer PIDs will be more likely to + // be searched for. + for j := len(pids) - 1; j >= 0; j-- { + if pidHasSocket(pids[j], socketName) { + return pids[j] } } return socket.UndefinedProcessID } -func findSocketFromPid(pid int, socketName string) bool { +func pidHasSocket(pid int, socketName string) bool { socketBase := "/proc/" + strconv.Itoa(pid) + "/fd" entries := readDirNames(socketBase) if len(entries) == 0 { diff --git a/network/state/lookup.go b/network/state/lookup.go index 42eb3da54..35006b2ca 100644 --- a/network/state/lookup.go +++ b/network/state/lookup.go @@ -28,6 +28,11 @@ var ( ErrPIDNotFound = errors.New("could not find pid for socket inode") ) +const ( + lookupTries = 5 + fastLookupTries = 2 +) + // Lookup looks for the given connection in the system state tables and returns the PID of the associated process and whether the connection is inbound. func Lookup(pktInfo *packet.Info, fast bool) (pid int, inbound bool, err error) { // auto-detect version diff --git a/network/state/system_default.go b/network/state/system_default.go index 973951c09..4b7989967 100644 --- a/network/state/system_default.go +++ b/network/state/system_default.go @@ -10,11 +10,6 @@ import ( "github.com/safing/portmaster/network/socket" ) -var ( - lookupTries = 20 // With a max wait of 5ms, this amounts to up to 100ms. - fastLookupTries = 2 -) - func init() { // This increases performance on unsupported system. // It's not critical at all and does not break anything if it fails. diff --git a/network/state/system_linux.go b/network/state/system_linux.go index 51954264f..c3e792a8a 100644 --- a/network/state/system_linux.go +++ b/network/state/system_linux.go @@ -13,16 +13,14 @@ var ( getUDP4Table = proc.GetUDP4Table getUDP6Table = proc.GetUDP6Table - lookupTries = 20 // With a max wait of 5ms, this amounts to up to 100ms. - fastLookupTries = 2 - - baseWaitTime = 3 * time.Millisecond + checkPIDTries = 5 + checkPIDBaseWaitTime = 5 * time.Millisecond ) // CheckPID checks the if socket info already has a PID and if not, tries to find it. // Depending on the OS, this might be a no-op. func CheckPID(socketInfo socket.Info, connInbound bool) (pid int, inbound bool, err error) { - for i := 1; i <= lookupTries; i++ { + for i := 1; i <= checkPIDTries; i++ { // look for PID pid = proc.GetPID(socketInfo) if pid != socket.UndefinedProcessID { @@ -31,10 +29,10 @@ func CheckPID(socketInfo socket.Info, connInbound bool) (pid int, inbound bool, } // every time, except for the last iteration - if i < lookupTries { + if i < checkPIDTries { // we found no PID, we could have been too fast, give the kernel some time to think - // back off timer: with 3ms baseWaitTime: 3, 6, 9, 12, 15, 18, 21ms - 84ms in total - time.Sleep(time.Duration(i+1) * baseWaitTime) + // back off timer: with 5ms baseWaitTime: 5, 10, 15, 20, 25 - 75ms in total + time.Sleep(time.Duration(i) * checkPIDBaseWaitTime) } } diff --git a/network/state/system_windows.go b/network/state/system_windows.go index a72d9195b..2a95a01e5 100644 --- a/network/state/system_windows.go +++ b/network/state/system_windows.go @@ -10,13 +10,6 @@ var ( getTCP6Table = iphelper.GetTCP6Table getUDP4Table = iphelper.GetUDP4Table getUDP6Table = iphelper.GetUDP6Table - - // With a max wait of 5ms, this amounts to up to 25ms, - // excluding potential data fetching time. - // Measured on Windows: ~150ms - lookupTries = 5 - - fastLookupTries = 2 ) // CheckPID checks the if socket info already has a PID and if not, tries to find it.