-
Notifications
You must be signed in to change notification settings - Fork 1
/
usermode.go
126 lines (109 loc) · 4.09 KB
/
usermode.go
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Invoked tracee-ebpf events from user mode
//
// This utility can be useful to generate information needed by signatures that
// is not provided by normal events in the kernel.
//
// Because the events in the kernel are invoked by other programs behavior, we
// cannot anticipate which events will be invoked and as a result what
// information will be extracted.
//
// This is critical because tracee-rules is independent, and doesn't have to run
// on the same machine as tracee-ebpf. This means that tracee-rules might lack
// basic information of the operating machine needed for some signatures.
//
// By creating user mode events this information could be intentionally
// collected and passed to tracee-ebpf afterwards.
package events
import (
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
"time"
"github.com/nextlinux/tracee/pkg/containers"
"github.com/nextlinux/tracee/pkg/containers/runtime"
"github.com/nextlinux/tracee/pkg/logger"
"github.com/nextlinux/tracee/types/trace"
)
const InitProcNsDir = "/proc/1/ns"
// InitNamespacesEvent collect the init process namespaces and create event from
// them.
func InitNamespacesEvent() trace.Event {
initNamespacesDef := Definitions.Get(InitNamespaces)
initNamespacesArgs := getInitNamespaceArguments()
initNamespacesEvent := trace.Event{
Timestamp: int(time.Now().UnixNano()),
ProcessName: "tracee-ebpf",
EventID: int(InitNamespaces),
EventName: initNamespacesDef.Name,
ArgsNum: len(initNamespacesArgs),
Args: initNamespacesArgs,
}
return initNamespacesEvent
}
// getInitNamespaceArguments fetches the namespaces of the init process and
// parse them into event arguments.
func getInitNamespaceArguments() []trace.Argument {
initNamespaces := fetchInitNamespaces()
eventDefinition := Definitions.Get(InitNamespaces)
initNamespacesArgs := make([]trace.Argument, len(eventDefinition.Params))
for i, arg := range initNamespacesArgs {
arg.ArgMeta = eventDefinition.Params[i]
arg.Value = initNamespaces[arg.Name]
initNamespacesArgs[i] = arg
}
return initNamespacesArgs
}
// fetchInitNamespaces fetches the namespaces values from the /proc/1/ns
// directory
func fetchInitNamespaces() map[string]uint32 {
var err error
var namespacesLinks []os.DirEntry
initNamespacesMap := make(map[string]uint32)
namespaceValueReg := regexp.MustCompile(":[[[:digit:]]*]")
namespacesLinks, err = os.ReadDir(InitProcNsDir)
if err != nil {
logger.Errorw("fetching init namespaces", "error", err)
}
for _, namespaceLink := range namespacesLinks {
linkString, _ := os.Readlink(filepath.Join(InitProcNsDir, namespaceLink.Name()))
trim := strings.Trim(namespaceValueReg.FindString(linkString), "[]:")
namespaceNumber, _ := strconv.ParseUint(trim, 10, 32)
initNamespacesMap[namespaceLink.Name()] = uint32(namespaceNumber)
}
return initNamespacesMap
}
// ExistingContainersEvents returns a list of events for each existing container
func ExistingContainersEvents(cts *containers.Containers, enrich bool) []trace.Event {
var events []trace.Event
def := Definitions.Get(ExistingContainer)
for id, info := range cts.GetContainers() {
container := runtime.ContainerMetadata{}
if enrich {
container, _ = cts.EnrichCgroupInfo(uint64(id))
}
args := []trace.Argument{
{ArgMeta: def.Params[0], Value: info.Runtime.String()},
{ArgMeta: def.Params[1], Value: info.Container.ContainerId},
{ArgMeta: def.Params[2], Value: info.Ctime.UnixNano()},
{ArgMeta: def.Params[3], Value: container.Image},
{ArgMeta: def.Params[3], Value: container.ImageDigest},
{ArgMeta: def.Params[4], Value: container.Name},
{ArgMeta: def.Params[5], Value: container.Pod.Name},
{ArgMeta: def.Params[6], Value: container.Pod.Namespace},
{ArgMeta: def.Params[7], Value: container.Pod.UID},
{ArgMeta: def.Params[8], Value: container.Pod.Sandbox},
}
existingContainerEvent := trace.Event{
Timestamp: int(time.Now().UnixNano()),
ProcessName: "tracee-ebpf",
EventID: int(ExistingContainer),
EventName: def.Name,
ArgsNum: len(args),
Args: args,
}
events = append(events, existingContainerEvent)
}
return events
}