1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
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 NewProcess(0, "")
}
if proc := findProcessInActivePidsCache(uint64(pid)); proc != nil {
return proc
}
proc := NewProcess(pid, "")
if err := proc.GetInfo(); err != nil {
log.Debug("[%d] FindProcess() error: %s", pid, err)
return nil
}
AddToActivePidsCache(uint64(pid), proc)
return proc
}
|