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 monitor
import (
"github.com/evilsocket/opensnitch/daemon/log"
"github.com/evilsocket/opensnitch/daemon/procmon"
"github.com/evilsocket/opensnitch/daemon/procmon/audit"
"github.com/evilsocket/opensnitch/daemon/procmon/ebpf"
)
var (
cacheMonitorsRunning = false
)
// List of errors that this package may return.
const (
NoError = iota
ProcFsErr
AuditdErr
EbpfErr
EbpfEventsErr
)
// Error wraps the type of error with its message
type Error struct {
What int
Msg error
}
// ReconfigureMonitorMethod configures a new method for parsing connections.
func ReconfigureMonitorMethod(newMonitorMethod, ebpfModulesPath string) *Error {
if procmon.GetMonitorMethod() == newMonitorMethod {
return nil
}
oldMethod := procmon.GetMonitorMethod()
if oldMethod == "" {
oldMethod = procmon.MethodProc
}
End()
procmon.SetMonitorMethod(newMonitorMethod)
// if the new monitor method fails to start, rollback the change and exit
// without saving the configuration. Otherwise we can end up with the wrong
// monitor method configured and saved to file.
err := Init(ebpfModulesPath)
if err.What > NoError {
log.Error("Reconf() -> Init() error: %v", err)
procmon.SetMonitorMethod(oldMethod)
return err
}
return nil
}
// End stops the way of parsing new connections.
func End() {
if procmon.MethodIsAudit() {
audit.Stop()
} else if procmon.MethodIsEbpf() {
ebpf.Stop()
}
}
// Init starts parsing connections using the method specified.
func Init(ebpfModulesPath string) (errm *Error) {
errm = &Error{}
if cacheMonitorsRunning == false {
go procmon.MonitorActivePids()
go procmon.CacheCleanerTask()
cacheMonitorsRunning = true
}
if procmon.MethodIsEbpf() {
err := ebpf.Start(ebpfModulesPath)
if err == nil {
log.Info("Process monitor method ebpf")
return errm
}
// ebpf main module loaded, we can use ebpf
// XXX: this will have to be rewritten when we'll have more events (bind, listen, etc)
if err.What == ebpf.EventsNotAvailable {
log.Info("Process monitor method ebpf")
log.Warning("opensnitch-procs.o not available: %s", err.Msg)
return errm
}
// we need to stop this method even if it has failed to start, in order to clean up the kprobes
// It helps with the error "cannot write...kprobe_events: file exists".
ebpf.Stop()
errm.What = err.What
errm.Msg = err.Msg
log.Warning("error starting ebpf monitor method: %v", err)
} else if procmon.MethodIsAudit() {
auditConn, err := audit.Start()
if err == nil {
log.Info("Process monitor method audit")
go audit.Reader(auditConn, (chan<- audit.Event)(audit.EventChan))
return &Error{AuditdErr, err}
}
errm.What = AuditdErr
errm.Msg = err
log.Warning("error starting audit monitor method: %v", err)
}
// if any of the above methods have failed, fallback to proc
log.Info("Process monitor method /proc")
procmon.SetMonitorMethod(procmon.MethodProc)
return errm
}
|