mirror of
https://github.com/evilsocket/opensnitch.git
synced 2025-03-04 08:34:40 +01:00
112 lines
3.4 KiB
Go
112 lines
3.4 KiB
Go
package procmon
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
|
"github.com/evilsocket/opensnitch/daemon/netstat"
|
|
"github.com/evilsocket/opensnitch/daemon/procmon/audit"
|
|
)
|
|
|
|
func getPIDFromAuditEvents(inode int, inodeKey string, expect string) (int, int) {
|
|
audit.Lock.RLock()
|
|
defer audit.Lock.RUnlock()
|
|
|
|
auditEvents := audit.GetEvents()
|
|
for n := 0; n < len(auditEvents); n++ {
|
|
pid := auditEvents[n].Pid
|
|
if inodeFound("/proc/", expect, inodeKey, inode, pid) {
|
|
return pid, n
|
|
}
|
|
}
|
|
for n := 0; n < len(auditEvents); n++ {
|
|
ppid := auditEvents[n].PPid
|
|
if inodeFound("/proc/", expect, inodeKey, inode, ppid) {
|
|
return ppid, n
|
|
}
|
|
}
|
|
return -1, -1
|
|
}
|
|
|
|
// GetInodeFromNetstat tries to obtain the inode of a connection from /proc/net/*
|
|
func GetInodeFromNetstat(netEntry *netstat.Entry, inodeList *[]int, protocol string, srcIP net.IP, srcPort uint, dstIP net.IP, dstPort uint) bool {
|
|
if netEntry = netstat.FindEntry(protocol, srcIP, srcPort, dstIP, dstPort); netEntry == nil {
|
|
log.Debug("Could not find netstat entry for: (%s) %d:%s -> %s:%d", protocol, srcPort, srcIP, dstIP, dstPort)
|
|
return false
|
|
}
|
|
if netEntry.INode > 0 {
|
|
log.Debug("connection found in netstat: %#v", netEntry)
|
|
*inodeList = append([]int{netEntry.INode}, *inodeList...)
|
|
return true
|
|
}
|
|
log.Debug("<== no inodes found for this connection: %#v", netEntry)
|
|
|
|
return false
|
|
}
|
|
|
|
// GetPIDFromINode tries to get the PID from a socket inode following these steps:
|
|
// 1. Get the PID from the cache of Inodes.
|
|
// 2. Get the PID from the cache of PIDs.
|
|
// 3. Look for the PID using one of these methods:
|
|
// - audit: listening for socket creation from auditd.
|
|
// - proc: search /proc
|
|
//
|
|
// If the PID is not found by one of the 2 first methods, it'll try it using /proc.
|
|
func GetPIDFromINode(inode int, inodeKey string) int {
|
|
found := -1
|
|
if inode <= 0 {
|
|
return found
|
|
}
|
|
start := time.Now()
|
|
|
|
expect := fmt.Sprintf("socket:[%d]", inode)
|
|
if cachedPidInode := inodesCache.getPid(inodeKey); cachedPidInode != -1 {
|
|
log.Debug("Inode found in cache: %v %v %v %v", time.Since(start), inodesCache.getPid(inodeKey), inode, inodeKey)
|
|
return cachedPidInode
|
|
}
|
|
|
|
cachedPid, pos := pidsCache.getPid(inode, inodeKey, expect)
|
|
if cachedPid != -1 {
|
|
log.Debug("Socket found in known pids %v, pid: %d, inode: %d, pos: %d, pids in cache: %d", time.Since(start), cachedPid, inode, pos, pidsCache.countItems())
|
|
pidsCache.sort(cachedPid)
|
|
inodesCache.add(inodeKey, "", cachedPid)
|
|
return cachedPid
|
|
}
|
|
|
|
if MethodIsAudit() {
|
|
if aPid, pos := getPIDFromAuditEvents(inode, inodeKey, expect); aPid != -1 {
|
|
log.Debug("PID found via audit events: %v, position: %d", time.Since(start), pos)
|
|
return aPid
|
|
}
|
|
}
|
|
if found == -1 || MethodIsProc() {
|
|
found = lookupPidInProc("/proc/", expect, inodeKey, inode)
|
|
}
|
|
log.Debug("new pid lookup took (%d): %v", found, time.Since(start))
|
|
|
|
return found
|
|
}
|
|
|
|
// FindProcess checks if a process exists given a PID.
|
|
// If it exists in /proc, a new Process{} object is returned with the details
|
|
// to identify a process (cmdline, name, environment variables, etc).
|
|
func FindProcess(pid int, interceptUnknown bool) *Process {
|
|
if interceptUnknown && pid < 0 {
|
|
return NewProcessEmpty(0, "")
|
|
}
|
|
|
|
if ev, _, found := EventsCache.IsInStore(pid, nil); found {
|
|
return &ev.Proc
|
|
}
|
|
|
|
proc := NewProcessEmpty(pid, "")
|
|
if err := proc.GetDetails(); err != nil {
|
|
log.Debug("[%d] FindProcess() error: %s", pid, err)
|
|
return nil
|
|
}
|
|
|
|
EventsCache.Add(proc)
|
|
return proc
|
|
}
|