2018-04-17 18:08:03 +02:00
|
|
|
package procmon
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io/ioutil"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
|
|
|
|
|
|
|
"github.com/evilsocket/ftrace"
|
2020-12-09 18:18:42 +01:00
|
|
|
"github.com/evilsocket/opensnitch/daemon/log"
|
2018-04-17 18:08:03 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
probeName = "opensnitch_exec_probe"
|
2018-08-12 13:02:33 -07:00
|
|
|
syscallName = "do_execve"
|
2018-04-17 18:08:03 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
type procData struct {
|
|
|
|
path string
|
|
|
|
args []string
|
|
|
|
}
|
|
|
|
|
|
|
|
var (
|
|
|
|
subEvents = []string{
|
|
|
|
"sched/sched_process_fork",
|
|
|
|
"sched/sched_process_exec",
|
|
|
|
"sched/sched_process_exit",
|
|
|
|
}
|
|
|
|
|
2020-03-03 23:51:25 +01:00
|
|
|
watcher = ftrace.NewProbe(probeName, syscallName, subEvents)
|
|
|
|
isAvailable = false
|
2020-06-14 20:14:24 +02:00
|
|
|
monitorMethod = MethodProc
|
2018-04-17 18:08:03 +02:00
|
|
|
|
|
|
|
index = make(map[int]*procData)
|
|
|
|
lock = sync.RWMutex{}
|
|
|
|
)
|
|
|
|
|
|
|
|
func forEachProcess(cb func(pid int, path string, args []string) bool) {
|
|
|
|
lock.RLock()
|
|
|
|
defer lock.RUnlock()
|
|
|
|
|
|
|
|
for pid, data := range index {
|
|
|
|
if cb(pid, data.path, data.args) == true {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func trackProcess(pid int) {
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
if _, found := index[pid]; found == false {
|
|
|
|
index[pid] = &procData{}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func trackProcessArgs(e ftrace.Event) {
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
|
|
|
|
if d, found := index[e.PID]; found == false {
|
|
|
|
index[e.PID] = &procData{
|
|
|
|
args: e.Argv(),
|
|
|
|
path: "",
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
d.args = e.Argv()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func trackProcessPath(e ftrace.Event) {
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
if d, found := index[e.PID]; found == false {
|
|
|
|
index[e.PID] = &procData{
|
|
|
|
path: e.Args["filename"],
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
d.path = e.Args["filename"]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func trackProcessExit(e ftrace.Event) {
|
|
|
|
lock.Lock()
|
|
|
|
defer lock.Unlock()
|
|
|
|
delete(index, e.PID)
|
|
|
|
}
|
|
|
|
|
|
|
|
func eventConsumer() {
|
|
|
|
for event := range watcher.Events() {
|
|
|
|
if event.IsSyscall == true {
|
|
|
|
trackProcessArgs(event)
|
|
|
|
} else if _, ok := event.Args["filename"]; ok && event.Name == "sched_process_exec" {
|
|
|
|
trackProcessPath(event)
|
|
|
|
} else if event.Name == "sched_process_exit" {
|
|
|
|
trackProcessExit(event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-24 19:15:42 +02:00
|
|
|
// Start enables the ftrace monitor method.
|
|
|
|
// This method configures a kprobe to intercept execve() syscalls.
|
|
|
|
// The kernel must have configured and enabled debugfs.
|
2018-04-17 18:08:03 +02:00
|
|
|
func Start() (err error) {
|
2018-04-18 02:00:12 +02:00
|
|
|
// start from a clean state
|
2020-10-24 19:15:42 +02:00
|
|
|
if err := watcher.Reset(); err != nil && watcher.Enabled() {
|
|
|
|
log.Warning("ftrace.Reset() error: %v", err)
|
|
|
|
}
|
2018-04-18 02:00:12 +02:00
|
|
|
|
2018-04-17 18:08:03 +02:00
|
|
|
if err = watcher.Enable(); err == nil {
|
2020-02-13 23:08:58 +01:00
|
|
|
isAvailable = true
|
|
|
|
|
2018-04-17 18:08:03 +02:00
|
|
|
go eventConsumer()
|
|
|
|
// track running processes
|
|
|
|
if ls, err := ioutil.ReadDir("/proc/"); err == nil {
|
|
|
|
for _, f := range ls {
|
|
|
|
if pid, err := strconv.Atoi(f.Name()); err == nil && f.IsDir() {
|
|
|
|
trackProcess(pid)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-10-24 19:15:42 +02:00
|
|
|
} else {
|
|
|
|
isAvailable = false
|
2018-04-17 18:08:03 +02:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2020-10-24 19:15:42 +02:00
|
|
|
// Stop disables ftrace monitor method, removing configured kprobe.
|
2018-04-17 18:08:03 +02:00
|
|
|
func Stop() error {
|
2020-02-13 23:08:58 +01:00
|
|
|
isAvailable = false
|
2018-04-17 18:08:03 +02:00
|
|
|
return watcher.Disable()
|
|
|
|
}
|
2020-02-13 23:08:58 +01:00
|
|
|
|
2020-10-24 19:15:42 +02:00
|
|
|
// IsWatcherAvailable checks if ftrace (debugfs) is
|
2020-02-13 23:08:58 +01:00
|
|
|
func IsWatcherAvailable() bool {
|
|
|
|
return isAvailable
|
|
|
|
}
|