diff --git a/process/database.go b/process/database.go index c5d0783f..a01ebe65 100644 --- a/process/database.go +++ b/process/database.go @@ -90,30 +90,40 @@ func (p *Process) Delete() { // CleanProcessStorage cleans the storage from old processes. func CleanProcessStorage(thresholdDuration time.Duration) { - processesLock.Lock() - defer processesLock.Unlock() + processesCopy := All() threshold := time.Now().Add(-thresholdDuration).Unix() + delete := false // clean primary processes - for _, p := range processes { + for _, p := range processesCopy { p.Lock() if !p.Virtual && p.LastCommEstablished < threshold && p.CommCount == 0 { - go p.Delete() + delete = true } p.Unlock() + + if delete { + p.Delete() + delete = false + } } // clean virtual processes - for _, p := range processes { + for _, p := range processesCopy { p.Lock() if p.Virtual { _, parentIsAlive := processes[p.ParentPid] if !parentIsAlive { - go p.Delete() + delete = true } } p.Unlock() + + if delete { + p.Delete() + delete = false + } } } diff --git a/process/proc/sockets.go b/process/proc/sockets.go index 49b443ea..067847f3 100644 --- a/process/proc/sockets.go +++ b/process/proc/sockets.go @@ -199,7 +199,7 @@ func getListeningSocket(localIP net.IP, localPort uint16, protocol uint8) (uid, return data[0], data[1], true } - return 0, 0, false + return -1, -1, false } func procDelimiter(c rune) bool { diff --git a/process/process.go b/process/process.go index 143a225e..e7ddc9dd 100644 --- a/process/process.go +++ b/process/process.go @@ -91,12 +91,22 @@ func (p *Process) RemoveCommunication() { // GetOrFindPrimaryProcess returns the highest process in the tree that matches the given PID. func GetOrFindPrimaryProcess(pid int) (*Process, error) { + if pid == -1 { + return UnknownProcess, nil + } + if pid == 0 { + return OSProcess, nil + } + process, err := loadProcess(pid) if err != nil { return nil, err } for { + if process.ParentPid == 0 { + return OSProcess, nil + } parentProcess, err := loadProcess(process.ParentPid) if err != nil { log.Tracef("process: could not get parent (%d): %s", process.Pid, err) @@ -126,6 +136,13 @@ func GetOrFindPrimaryProcess(pid int) (*Process, error) { // GetOrFindProcess returns the process for the given PID. func GetOrFindProcess(pid int) (*Process, error) { + if pid == -1 { + return UnknownProcess, nil + } + if pid == 0 { + return OSProcess, nil + } + p, err := loadProcess(pid) if err != nil { return nil, err @@ -137,6 +154,13 @@ func GetOrFindProcess(pid int) (*Process, error) { } func loadProcess(pid int) (*Process, error) { + if pid == -1 { + return UnknownProcess, nil + } + if pid == 0 { + return OSProcess, nil + } + process, ok := GetProcessFromStorage(pid) if ok { return process, nil diff --git a/process/process_linux.go b/process/process_linux.go index ebfa4104..cc871dad 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -19,3 +19,8 @@ func (m *Process) IsSystem() bool { func (m *Process) IsKernel() bool { return m.Pid == 0 } + +// specialOSInit does special OS specific Process initialization. +func (m *Process) specialOSInit() { + +} diff --git a/process/process_windows.go b/process/process_windows.go index 5e7f2cdc..1efdb946 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -1,24 +1,46 @@ package process -import "strings" +import ( + "fmt" + "strings" + + "github.com/Safing/portbase/log" + "github.com/Safing/portbase/utils/osdetail" +) // IsUser returns whether the process is run by a normal user. -func (m *Process) IsUser() bool { - return m.Pid != 4 && // Kernel - !strings.HasPrefix(m.UserName, "NT") // NT-Authority (localized!) +func (p *Process) IsUser() bool { + return p.Pid != 4 && // Kernel + !strings.HasPrefix(p.UserName, "NT") // NT-Authority (localized!) } // IsAdmin returns whether the process is run by an admin user. -func (m *Process) IsAdmin() bool { - return strings.HasPrefix(m.UserName, "NT") // NT-Authority (localized!) +func (p *Process) IsAdmin() bool { + return strings.HasPrefix(p.UserName, "NT") // NT-Authority (localized!) } // IsSystem returns whether the process is run by the operating system. -func (m *Process) IsSystem() bool { - return m.Pid == 4 +func (p *Process) IsSystem() bool { + return p.Pid == 4 } // IsKernel returns whether the process is the Kernel. -func (m *Process) IsKernel() bool { - return m.Pid == 4 +func (p *Process) IsKernel() bool { + return p.Pid == 4 +} + +// specialOSInit does special OS specific Process initialization. +func (p *Process) specialOSInit() { + // add svchost.exe service names to Name + if p.ExecName == "svchost.exe" { + svcNames, err := osdetail.GetServiceNames(int32(p.Pid)) + switch err { + case nil: + p.Name += fmt.Sprintf(" (%s)", svcNames) + case osdetail.ErrServiceNotFound: + log.Tracef("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) + default: + log.Warningf("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) + } + } } diff --git a/process/unknown.go b/process/unknown.go index 07f62056..4f6cde12 100644 --- a/process/unknown.go +++ b/process/unknown.go @@ -9,8 +9,18 @@ var ( ParentPid: -1, Name: "Unknown Processes", } + + // OSProcess is used to represent the Kernel. + OSProcess = &Process{ + UserID: 0, + UserName: "Kernel", + Pid: 0, + ParentPid: 0, + Name: "Operating System", + } ) func init() { UnknownProcess.Save() + OSProcess.Save() }