Skip to content

Commit

Permalink
Added system requirements check
Browse files Browse the repository at this point in the history
Added flag to check system requirements.
Related: #774
  • Loading branch information
gustavo-iniguez-goya committed May 18, 2023
1 parent 6b297a9 commit 8513c0d
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 12 deletions.
28 changes: 28 additions & 0 deletions daemon/core/gzip.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package core

import (
"compress/gzip"
"io/ioutil"
"os"
)

// ReadGzipFile reads a gzip to text.
func ReadGzipFile(filename string) ([]byte, error) {
fd, err := os.Open(filename)
if err != nil {
return nil, err
}
defer fd.Close()

gz, err := gzip.NewReader(fd)
if err != nil {
return nil, err
}
defer gz.Close()

s, err := ioutil.ReadAll(gz)
if err != nil {
return nil, err
}
return s, nil
}
135 changes: 135 additions & 0 deletions daemon/core/system.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package core

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"os"
"regexp"
"strings"

"github.com/evilsocket/opensnitch/daemon/log"
)

var (
Expand All @@ -21,3 +28,131 @@ func GetKernelVersion() string {
version, _ := ioutil.ReadFile("/proc/sys/kernel/osrelease")
return strings.Replace(string(version), "\n", "", -1)
}

// CheckSysRequirements checks system features we need to work properly
func CheckSysRequirements() {
type checksT struct {
RegExps []string
Reason string
}
type ReqsList struct {
Item string
Checks checksT
}
kVer := GetKernelVersion()

log.Raw("\n\t%sChecking system requirements for kernel version %s%s\n", log.FG_WHITE+log.BG_LBLUE, kVer, log.RESET)
log.Raw("%s------------------------------------------------------------------------------%s\n\n", log.FG_WHITE+log.BG_LBLUE, log.RESET)

confFile := fmt.Sprint("/boot/config-", kVer)
var fileContent []byte
var err error
if Exists(confFile) {
fileContent, err = os.ReadFile(confFile)
} else {
confFile = "/proc/config.gz"
fileContent, err = ReadGzipFile(confFile)
}
if err != nil {
log.Error("%s not found", confFile)
return
}

// TODO: check loaded/configured modules (nfnetlink, nfnetlink_queue, xt_NFQUEUE, etc)
// Other items to check:
// CONFIG_NETFILTER_NETLINK
// CONFIG_NETFILTER_NETLINK_QUEUE
const reqsList = `
[
{
"Item": "kprobes",
"Checks": {
"Regexps": [
"CONFIG_KPROBES=y",
"CONFIG_KPROBES_ON_FTRACE=y",
"CONFIG_KPROBES_ON_FTRACE=y",
"CONFIG_HAVE_KPROBES=y",
"CONFIG_HAVE_KPROBES_ON_FTRACE=y",
"CONFIG_KPROBE_EVENTS=y"
],
"Reason": " - KPROBES not fully supported by this kernel."
}
},
{
"Item": "uprobes",
"Checks": {
"Regexps": [
"CONFIG_UPROBES=y",
"CONFIG_UPROBE_EVENTS=y"
],
"Reason": " * UPROBES not supported. Common error => cannot open uprobe_events: open /sys/kernel/debug/tracing/uprobe_events"
}
},
{
"Item": "ftrace",
"Checks": {
"Regexps": [
"CONFIG_FTRACE=y"
],
"Reason": " - CONFIG_TRACE=y not set. Common error => Error while loading kprobes: invalid argument."
}
},
{
"Item": "syscalls",
"Checks": {
"Regexps": [
"CONFIG_HAVE_SYSCALL_TRACEPOINTS=y",
"CONFIG_FTRACE_SYSCALLS=y"
],
"Reason": " - CONFIG_FTRACE_SYSCALLS or CONFIG_HAVE_SYSCALL_TRACEPOINTS not set. Common error => error enabling tracepoint tracepoint/syscalls/sys_enter_execve: cannot read tracepoint id"
}
},
{
"Item": "nfqueue",
"Checks": {
"Regexps": [
"CONFIG_NETFILTER_XT_TARGET_NFQUEUE=[my]"
],
"Reason": " * NFQUEUE netfilter extension not supported by this kernel."
}
}
]
`

reqsFullfiled := true
dec := json.NewDecoder(strings.NewReader(reqsList))
for {
var reqs []ReqsList
if err := dec.Decode(&reqs); err == io.EOF {
break
} else if err != nil {
log.Error("%s", err)
break
}
for _, req := range reqs {
checkOk := true
for _, trex := range req.Checks.RegExps {
fmt.Printf("\tChecking => %s\n", trex)
re, err := regexp.Compile(trex)
if err != nil {
fmt.Printf("\t%s %s\n", log.Bold(log.Red("Invalid regexp =>")), log.Red(trex))
continue
}
if re.Find(fileContent) == nil {
fmt.Printf("\t%s\n", log.Red(req.Checks.Reason))
checkOk = false
}
}
if checkOk {
fmt.Printf("\n\t* %s\t %s\n", log.Bold(log.Green(req.Item)), log.Bold(log.Green("✔")))
} else {
reqsFullfiled = false
fmt.Printf("\n\t* %s\t %s\n", log.Bold(log.Red(req.Item)), log.Bold(log.Red("✘")))
}
fmt.Println()
}
}
if !reqsFullfiled {
log.Raw("\n%sWARNING:%s Your kernel doesn't support some of the features OpenSnitch needs:\nRead more: https://github.com/evilsocket/opensnitch/issues/774\n", log.FG_WHITE+log.BG_YELLOW, log.RESET)
}
}
30 changes: 18 additions & 12 deletions daemon/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,19 @@ import (
)

var (
showVersion = false
procmonMethod = ""
logFile = ""
rulesPath = "rules"
noLiveReload = false
queueNum = 0
repeatQueueNum int //will be set later to queueNum + 1
workers = 16
debug = false
warning = false
important = false
errorlog = false
showVersion = false
checkRequirements = false
procmonMethod = ""
logFile = ""
rulesPath = "rules"
noLiveReload = false
queueNum = 0
repeatQueueNum int //will be set later to queueNum + 1
workers = 16
debug = false
warning = false
important = false
errorlog = false

uiSocket = ""
uiClient = (*ui.Client)(nil)
Expand All @@ -90,6 +91,7 @@ var (

func init() {
flag.BoolVar(&showVersion, "version", debug, "Show daemon version of this executable and exit.")
flag.BoolVar(&checkRequirements, "check-requirements", debug, "Check system requirements for incompatibilities.")

flag.StringVar(&procmonMethod, "process-monitor-method", procmonMethod, "How to search for processes path. Options: ftrace, audit (experimental), ebpf (experimental), proc (default)")
flag.StringVar(&uiSocket, "ui-socket", uiSocket, "Path the UI gRPC service listener (https://github.com/grpc/grpc/blob/master/doc/naming.md).")
Expand Down Expand Up @@ -463,6 +465,10 @@ func main() {
fmt.Println(core.Version)
os.Exit(0)
}
if checkRequirements {
core.CheckSysRequirements()
os.Exit(0)
}

setupLogging()
setupProfiling()
Expand Down

0 comments on commit 8513c0d

Please sign in to comment.