From 0f7e93acdcb79e29235df367ff6e3eb3aa8f4338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20I=C3=B1iguez=20Goia?= Date: Tue, 20 Apr 2021 16:31:49 +0200 Subject: [PATCH] fixed parsing /proc/$pid/stat starttime field On systems that have been running for a long time (for example 552 days) we were failing parsing the starttime field: ``` Could not find or convert Starttime. This should never happen. Please report this incident to the Opensnitch developers: strconv.Atoi: parsing "4242026842": value out of range ``` - extra: fixed tests. --- daemon/procmon/activepids.go | 20 ++++++++++---------- daemon/procmon/activepids_test.go | 8 ++++---- daemon/procmon/parse.go | 6 +++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/daemon/procmon/activepids.go b/daemon/procmon/activepids.go index 5a6a2bc1..1c4c2b6f 100644 --- a/daemon/procmon/activepids.go +++ b/daemon/procmon/activepids.go @@ -15,11 +15,11 @@ type value struct { Process *Process //Starttime uniquely identifies a process, it is the 22nd value in /proc//stat //if another process starts with the same PID, it's Starttime will be unique - Starttime uint32 + Starttime uint64 } var ( - activePids = make(map[uint32]value) + activePids = make(map[uint64]value) activePidsLock = sync.RWMutex{} ) @@ -38,14 +38,14 @@ func MonitorActivePids() { deleteProcEntry(int(k)) continue } - startTime, err := strconv.Atoi(strings.Split(string(data), " ")[21]) + startTime, err := strconv.ParseInt(strings.Split(string(data), " ")[21], 10, 64) if err != nil { - log.Error("Could not find or convert Starttime. This should never happen. Please report this incident to the Opensnitch developers.") + log.Error("Could not find or convert Starttime. This should never happen. Please report this incident to the Opensnitch developers: %v", err) delete(activePids, k) deleteProcEntry(int(k)) continue } - if uint32(startTime) != v.Starttime { + if uint64(startTime) != v.Starttime { //extremely unlikely: the original process has quit and another process //was started with the same PID - all this in less than 1 second log.Error("Same PID but different Starttime. Please report this incident to the Opensnitch developers.") @@ -58,7 +58,7 @@ func MonitorActivePids() { } } -func findProcessInActivePidsCache(pid uint32) *Process { +func findProcessInActivePidsCache(pid uint64) *Process { activePidsLock.Lock() defer activePidsLock.Unlock() if value, ok := activePids[pid]; ok { @@ -67,23 +67,23 @@ func findProcessInActivePidsCache(pid uint32) *Process { return nil } -func addToActivePidsCache(pid uint32, proc *Process) { +func addToActivePidsCache(pid uint64, proc *Process) { data, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/stat", pid)) if err != nil { //most likely the process has quit by now return } - startTime, err2 := strconv.Atoi(strings.Split(string(data), " ")[21]) + startTime, err2 := strconv.ParseInt(strings.Split(string(data), " ")[21], 10, 64) if err2 != nil { - log.Error("Could not find or convert Starttime. This should never happen. Please report this incident to the Opensnitch developers.") + log.Error("Could not find or convert Starttime. This should never happen. Please report this incident to the Opensnitch developers: %v", err) return } activePidsLock.Lock() activePids[pid] = value{ Process: proc, - Starttime: uint32(startTime), + Starttime: uint64(startTime), } activePidsLock.Unlock() } diff --git a/daemon/procmon/activepids_test.go b/daemon/procmon/activepids_test.go index 48d9f575..88ca598e 100644 --- a/daemon/procmon/activepids_test.go +++ b/daemon/procmon/activepids_test.go @@ -28,7 +28,7 @@ func TestMonitorActivePids(t *testing.T) { fmt.Println("tmp dir", tmpDir) defer os.RemoveAll(tmpDir) - go monitorActivePids() + go MonitorActivePids() //build a "helper binary" with "go test -c -o /tmp/path" and put it into a tmp dir helperBinaryPath := tmpDir + "/helper1" @@ -58,7 +58,7 @@ func TestMonitorActivePids(t *testing.T) { pid := helperCmd.Process.Pid proc := NewProcess(pid, helperBinaryPath) helperProcs = append(helperProcs, proc) - addToActivePidsCache(uint32(pid), proc) + addToActivePidsCache(uint64(pid), proc) } //sleep to make sure all processes started before we proceed time.Sleep(time.Second * 1) @@ -66,7 +66,7 @@ func TestMonitorActivePids(t *testing.T) { for i := 0; i < numberOfHelpers; i++ { proc := helperProcs[i] pid := proc.ID - foundProc := findProcessInActivePidsCache(uint32(pid)) + foundProc := findProcessInActivePidsCache(uint64(pid)) if foundProc == nil { t.Error("PID not found among active processes", pid) } @@ -84,7 +84,7 @@ func TestMonitorActivePids(t *testing.T) { time.Sleep(time.Second * 1) //make sure only the alive process is in the cache - foundProc := findProcessInActivePidsCache(uint32(helperProcs[numberOfHelpers-1].ID)) + foundProc := findProcessInActivePidsCache(uint64(helperProcs[numberOfHelpers-1].ID)) if foundProc == nil { t.Error("last alive PID is not found among active processes", foundProc) } diff --git a/daemon/procmon/parse.go b/daemon/procmon/parse.go index 061ac1c3..228f2a2f 100644 --- a/daemon/procmon/parse.go +++ b/daemon/procmon/parse.go @@ -92,7 +92,7 @@ func FindProcess(pid int, interceptUnknown bool) *Process { return NewProcess(0, "") } - if proc := findProcessInActivePidsCache(uint32(pid)); proc != nil { + if proc := findProcessInActivePidsCache(uint64(pid)); proc != nil { return proc } @@ -110,7 +110,7 @@ func FindProcess(pid int, interceptUnknown bool) *Process { proc.readEnv() proc.cleanPath() - addToActivePidsCache(uint32(pid), proc) + addToActivePidsCache(uint64(pid), proc) return proc } } @@ -128,7 +128,7 @@ func FindProcess(pid int, interceptUnknown bool) *Process { proc.readEnv() proc.cleanPath() - addToActivePidsCache(uint32(pid), proc) + addToActivePidsCache(uint64(pid), proc) return proc } return nil