Skip to content

Commit 1ae20c3

Browse files
ebpf: fixed getting ppid, skip failed execve's
- Fixed getting ppid (precompiled .o won't probably work). - Skip failed execve* calls. (cherry picked from commit 68c2c8a)
1 parent eafb70f commit 1ae20c3

File tree

5 files changed

+119
-50
lines changed

5 files changed

+119
-50
lines changed

daemon/procmon/ebpf/cache.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
)
99

1010
// NewExecEvent constructs a new execEvent from the arguments.
11-
func NewExecEvent(pid, ppid, uid uint64, path string, comm [16]byte) *execEvent {
11+
func NewExecEvent(pid, ppid, uid uint32, path string, comm [16]byte) *execEvent {
1212
ev := &execEvent{
1313
Type: EV_TYPE_EXEC,
1414
PID: pid,
@@ -31,18 +31,18 @@ type execEventItem struct {
3131
}
3232

3333
type eventsStore struct {
34-
execEvents map[uint64]*execEventItem
34+
execEvents map[uint32]*execEventItem
3535
sync.RWMutex
3636
}
3737

3838
// NewEventsStore creates a new store of events.
3939
func NewEventsStore() *eventsStore {
4040
return &eventsStore{
41-
execEvents: make(map[uint64]*execEventItem),
41+
execEvents: make(map[uint32]*execEventItem),
4242
}
4343
}
4444

45-
func (e *eventsStore) add(key uint64, event execEvent, proc procmon.Process) {
45+
func (e *eventsStore) add(key uint32, event execEvent, proc procmon.Process) {
4646
e.Lock()
4747
defer e.Unlock()
4848
e.execEvents[key] = &execEventItem{
@@ -51,14 +51,14 @@ func (e *eventsStore) add(key uint64, event execEvent, proc procmon.Process) {
5151
}
5252
}
5353

54-
func (e *eventsStore) isInStore(key uint64) (item *execEventItem, found bool) {
54+
func (e *eventsStore) isInStore(key uint32) (item *execEventItem, found bool) {
5555
e.RLock()
5656
defer e.RUnlock()
5757
item, found = e.execEvents[key]
5858
return
5959
}
6060

61-
func (e *eventsStore) delete(key uint64) {
61+
func (e *eventsStore) delete(key uint32) {
6262
e.Lock()
6363
defer e.Unlock()
6464
delete(e.execEvents, key)

daemon/procmon/ebpf/events.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,17 @@ const TaskCommLen = 16
3030

3131
type execEvent struct {
3232
Type uint64
33-
PID uint64
34-
PPID uint64
35-
UID uint64
36-
ArgsCount uint64
37-
ArgsPartial uint64
33+
PID uint32
34+
UID uint32
35+
PPID uint32
36+
RetCode uint32
37+
ArgsCount uint8
38+
ArgsPartial uint8
3839
Filename [MaxPathLen]byte
3940
Args [MaxArgs][MaxArgLen]byte
4041
Comm [TaskCommLen]byte
42+
Pad1 uint16
43+
Pad2 uint32
4144
}
4245

4346
// Struct that holds the metadata of a connection.
@@ -91,6 +94,8 @@ func initEventsStreamer() {
9194
"tracepoint/sched/sched_process_exit",
9295
"tracepoint/syscalls/sys_enter_execve",
9396
"tracepoint/syscalls/sys_enter_execveat",
97+
"tracepoint/syscalls/sys_exit_execve",
98+
"tracepoint/syscalls/sys_exit_execveat",
9499
//"tracepoint/sched/sched_process_exec",
95100
//"tracepoint/sched/sched_process_fork",
96101
}
@@ -198,6 +203,7 @@ func event2process(event *execEvent) (proc *procmon.Process) {
198203
proc.ReadCwd()
199204
proc.ReadEnv()
200205
proc.UID = int(event.UID)
206+
proc.PPID = int(event.PPID)
201207

202208
if event.ArgsPartial == 0 {
203209
for i := 0; i < int(event.ArgsCount); i++ {

daemon/procmon/ebpf/find.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ func findConnProcess(value *networkEventT, connKey string) (proc *procmon.Proces
165165
proc.UID = int(value.UID)
166166

167167
err := proc.ReadPath()
168-
if ev, found := execEvents.isInStore(value.Pid); found {
168+
if ev, found := execEvents.isInStore(uint32(value.Pid)); found {
169169
// use socket's UID. See above why ^
170170
ev.Proc.UID = proc.UID
171171
ev.Proc.ReadCmdline()
@@ -186,8 +186,8 @@ func findConnProcess(value *networkEventT, connKey string) (proc *procmon.Proces
186186
log.Debug("[ebpf conn] not in cache, NOR in execEvents: %s, %d -> %s", connKey, proc.ID, proc.Path)
187187
// We'll end here if the events module has not been loaded, or if the process is not in cache.
188188
proc.GetInfo()
189-
execEvents.add(value.Pid,
190-
*NewExecEvent(value.Pid, 0, value.UID, proc.Path, value.Comm),
189+
execEvents.add(uint32(value.Pid),
190+
*NewExecEvent(uint32(value.Pid), 0, uint32(value.UID), proc.Path, value.Comm),
191191
*proc)
192192
}
193193

ebpf_prog/common.h

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,55 @@ enum events_type {
3434
EVENT_SCHED_EXIT,
3535
};
3636

37+
struct trace_ev_common {
38+
short common_type;
39+
char common_flags;
40+
char common_preempt_count;
41+
int common_pid;
42+
};
43+
44+
struct trace_sys_enter_execve {
45+
struct trace_ev_common ext;
46+
47+
int __syscall_nr;
48+
char *filename;
49+
const char *const *argv;
50+
const char *const *envp;
51+
};
52+
53+
struct trace_sys_enter_execveat {
54+
struct trace_ev_common ext;
55+
56+
int __syscall_nr;
57+
char *filename;
58+
const char *const *argv;
59+
const char *const *envp;
60+
int flags;
61+
};
62+
63+
struct trace_sys_exit_execve {
64+
struct trace_ev_common ext;
65+
66+
int __syscall_nr;
67+
long ret;
68+
};
69+
3770

3871
struct data_t {
3972
u64 type;
40-
u64 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
41-
u64 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
42-
u64 uid;
43-
u64 args_count;
44-
u64 args_partial;
73+
u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
74+
u32 uid;
75+
// Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
76+
u32 ppid;
77+
u32 ret_code;
78+
u8 args_count;
79+
u8 args_partial;
4580
char filename[MAX_PATH_LEN];
4681
char args[MAX_ARGS][MAX_ARG_SIZE];
4782
char comm[TASK_COMM_LEN];
48-
}__attribute__((packed));
83+
u16 pad1;
84+
u32 pad2;
85+
};
4986

5087
//-----------------------------------------------------------------------------
5188
// maps

ebpf_prog/opensnitch-procs.c

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ struct bpf_map_def SEC("maps/proc-events") events = {
1010
.max_entries = 256, // max cpus
1111
};
1212

13+
struct bpf_map_def SEC("maps/execMap") execMap = {
14+
.type = BPF_MAP_TYPE_HASH,
15+
.key_size = sizeof(u32),
16+
.value_size = sizeof(struct data_t),
17+
.max_entries = 256,
18+
};
19+
20+
1321
static __always_inline void new_event(struct data_t* data)
1422
{
1523
// initializing variables with __builtin_memset() is required
@@ -23,15 +31,28 @@ static __always_inline void new_event(struct data_t* data)
2331
bpf_probe_read(&parent, sizeof(parent), &task->real_parent);
2432
data->pid = bpf_get_current_pid_tgid() >> 32;
2533

26-
// FIXME: always 0?
2734
#if !defined(__arm__) && !defined(__i386__)
2835
// on i686 -> invalid read from stack
29-
bpf_probe_read(&data->ppid, sizeof(data->ppid), &parent->tgid);
36+
bpf_probe_read(&data->ppid, sizeof(u32), &parent->tgid);
3037
#endif
3138
data->uid = bpf_get_current_uid_gid() & 0xffffffff;
3239
bpf_get_current_comm(&data->comm, sizeof(data->comm));
3340
};
3441

42+
static __always_inline void __handle_exit_execve(struct trace_sys_exit_execve *ctx)
43+
{
44+
u64 pid_tgid = bpf_get_current_pid_tgid();
45+
struct data_t *proc = bpf_map_lookup_elem(&execMap, &pid_tgid);
46+
if (proc == NULL) { return; }
47+
if (ctx->ret != 0) { goto out; }
48+
proc->ret_code = ctx->ret;
49+
50+
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, proc, sizeof(*proc));
51+
52+
out:
53+
bpf_map_delete_elem(&execMap, &pid_tgid);
54+
}
55+
3556
// https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html
3657
// bprm_execve REGS_PARM3
3758
// https://elixir.bootlin.com/linux/latest/source/fs/exec.c#L1796
@@ -50,16 +71,20 @@ int tracepoint__sched_sched_process_exit(struct pt_regs *ctx)
5071
return 0;
5172
};
5273

53-
struct trace_sys_enter_execve {
54-
short common_type;
55-
char common_flags;
56-
char common_preempt_count;
57-
int common_pid;
58-
int __syscall_nr;
59-
char *filename;
60-
const char *const *argv;
61-
const char *const *envp;
74+
SEC("tracepoint/syscalls/sys_exit_execve")
75+
int tracepoint__syscalls_sys_exit_execve(struct trace_sys_exit_execve *ctx)
76+
{
77+
__handle_exit_execve(ctx);
78+
return 0;
6279
};
80+
81+
SEC("tracepoint/syscalls/sys_exit_execveat")
82+
int tracepoint__syscalls_sys_exit_execveat(struct trace_sys_exit_execve *ctx)
83+
{
84+
__handle_exit_execve(ctx);
85+
return 0;
86+
};
87+
6388
SEC("tracepoint/syscalls/sys_enter_execve")
6489
int tracepoint__syscalls_sys_enter_execve(struct trace_sys_enter_execve* ctx)
6590
{
@@ -93,24 +118,19 @@ int tracepoint__syscalls_sys_enter_execve(struct trace_sys_enter_execve* ctx)
93118
}
94119
#endif
95120

96-
// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
97-
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
98-
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
99-
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
121+
// in case of failure adding the item to the map, send it directly
122+
u64 pid_tgid = bpf_get_current_pid_tgid();
123+
if (bpf_map_update_elem(&execMap, &pid_tgid, data, BPF_ANY) != 0) {
124+
125+
// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
126+
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
127+
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
128+
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
129+
}
130+
100131
return 0;
101132
};
102133

103-
struct trace_sys_enter_execveat {
104-
short common_type;
105-
char common_flags;
106-
char common_preempt_count;
107-
int common_pid;
108-
int __syscall_nr;
109-
char *filename;
110-
const char *const *argv;
111-
const char *const *envp;
112-
int flags;
113-
};
114134
SEC("tracepoint/syscalls/sys_enter_execveat")
115135
int tracepoint__syscalls_sys_enter_execveat(struct trace_sys_enter_execveat* ctx)
116136
{
@@ -140,10 +160,16 @@ int tracepoint__syscalls_sys_enter_execveat(struct trace_sys_enter_execveat* ctx
140160
data->args_count++;
141161
}
142162

143-
// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
144-
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
145-
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
146-
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
163+
// in case of failure adding the item to the map, send it directly
164+
u64 pid_tgid = bpf_get_current_pid_tgid();
165+
if (bpf_map_update_elem(&execMap, &pid_tgid, data, BPF_ANY) != 0) {
166+
167+
// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
168+
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
169+
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
170+
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
171+
}
172+
147173
return 0;
148174
};
149175

0 commit comments

Comments
 (0)