Skip to content

Commit

Permalink
ebpf: fixed getting ppid, skip failed execve's
Browse files Browse the repository at this point in the history
 - Fixed getting ppid (precompiled .o won't probably work).
 - Skip failed execve* calls.
  • Loading branch information
gustavo-iniguez-goya committed Dec 26, 2023
1 parent ffb7668 commit 68c2c8a
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 42 deletions.
21 changes: 15 additions & 6 deletions daemon/procmon/ebpf/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,17 @@ const TaskCommLen = 16

type execEvent struct {
Type uint64
PID uint64
PPID uint64
UID uint64
ArgsCount uint64
ArgsPartial uint64
PID uint32
UID uint32
PPID uint32
RetCode uint32
ArgsCount uint8
ArgsPartial uint8
Filename [MaxPathLen]byte
Args [MaxArgs][MaxArgLen]byte
Comm [TaskCommLen]byte
Pad1 uint16
Pad2 uint32
}

// Struct that holds the metadata of a connection.
Expand Down Expand Up @@ -91,6 +94,8 @@ func initEventsStreamer() *Error {
"tracepoint/sched/sched_process_exit",
"tracepoint/syscalls/sys_enter_execve",
"tracepoint/syscalls/sys_enter_execveat",
"tracepoint/syscalls/sys_exit_execve",
"tracepoint/syscalls/sys_exit_execveat",
//"tracepoint/sched/sched_process_exec",
//"tracepoint/sched/sched_process_fork",
}
Expand Down Expand Up @@ -228,7 +233,11 @@ func event2process(event *execEvent) (proc *procmon.Process) {
return nil
}
}
proc.ReadPPID()
if event.PPID != 0 {
proc.PPID = int(event.PPID)
} else {
proc.ReadPPID()
}

if event.ArgsPartial == 0 {
for i := 0; i < int(event.ArgsCount); i++ {
Expand Down
49 changes: 43 additions & 6 deletions ebpf_prog/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,55 @@ enum events_type {
EVENT_SCHED_EXIT,
};

struct trace_ev_common {
short common_type;
char common_flags;
char common_preempt_count;
int common_pid;
};

struct trace_sys_enter_execve {
struct trace_ev_common ext;

int __syscall_nr;
char *filename;
const char *const *argv;
const char *const *envp;
};

struct trace_sys_enter_execveat {
struct trace_ev_common ext;

int __syscall_nr;
char *filename;
const char *const *argv;
const char *const *envp;
int flags;
};

struct trace_sys_exit_execve {
struct trace_ev_common ext;

int __syscall_nr;
long ret;
};


struct data_t {
u64 type;
u64 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
u64 ppid; // Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
u64 uid;
u64 args_count;
u64 args_partial;
u32 pid; // PID as in the userspace term (i.e. task->tgid in kernel)
u32 uid;
// Parent PID as in the userspace term (i.e task->real_parent->tgid in kernel)
u32 ppid;
u32 ret_code;
u8 args_count;
u8 args_partial;
char filename[MAX_PATH_LEN];
char args[MAX_ARGS][MAX_ARG_SIZE];
char comm[TASK_COMM_LEN];
}__attribute__((packed));
u16 pad1;
u32 pad2;
};

//-----------------------------------------------------------------------------
// maps
Expand Down
86 changes: 56 additions & 30 deletions ebpf_prog/opensnitch-procs.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ struct bpf_map_def SEC("maps/proc-events") events = {
.max_entries = 256, // max cpus
};

struct bpf_map_def SEC("maps/execMap") execMap = {
.type = BPF_MAP_TYPE_HASH,
.key_size = sizeof(u32),
.value_size = sizeof(struct data_t),
.max_entries = 256,
};


static __always_inline void new_event(struct data_t* data)
{
// initializing variables with __builtin_memset() is required
Expand All @@ -23,15 +31,28 @@ static __always_inline void new_event(struct data_t* data)
bpf_probe_read(&parent, sizeof(parent), &task->real_parent);
data->pid = bpf_get_current_pid_tgid() >> 32;

// FIXME: always 0?
#if !defined(__arm__) && !defined(__i386__)
// on i686 -> invalid read from stack
bpf_probe_read(&data->ppid, sizeof(data->ppid), &parent->tgid);
bpf_probe_read(&data->ppid, sizeof(u32), &parent->tgid);
#endif
data->uid = bpf_get_current_uid_gid() & 0xffffffff;
bpf_get_current_comm(&data->comm, sizeof(data->comm));
};

static __always_inline void __handle_exit_execve(struct trace_sys_exit_execve *ctx)
{
u64 pid_tgid = bpf_get_current_pid_tgid();
struct data_t *proc = bpf_map_lookup_elem(&execMap, &pid_tgid);
if (proc == NULL) { return; }
if (ctx->ret != 0) { goto out; }
proc->ret_code = ctx->ret;

bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, proc, sizeof(*proc));

out:
bpf_map_delete_elem(&execMap, &pid_tgid);
}

// https://0xax.gitbooks.io/linux-insides/content/SysCall/linux-syscall-4.html
// bprm_execve REGS_PARM3
// https://elixir.bootlin.com/linux/latest/source/fs/exec.c#L1796
Expand All @@ -50,16 +71,20 @@ int tracepoint__sched_sched_process_exit(struct pt_regs *ctx)
return 0;
};

struct trace_sys_enter_execve {
short common_type;
char common_flags;
char common_preempt_count;
int common_pid;
int __syscall_nr;
char *filename;
const char *const *argv;
const char *const *envp;
SEC("tracepoint/syscalls/sys_exit_execve")
int tracepoint__syscalls_sys_exit_execve(struct trace_sys_exit_execve *ctx)
{
__handle_exit_execve(ctx);
return 0;
};

SEC("tracepoint/syscalls/sys_exit_execveat")
int tracepoint__syscalls_sys_exit_execveat(struct trace_sys_exit_execve *ctx)
{
__handle_exit_execve(ctx);
return 0;
};

SEC("tracepoint/syscalls/sys_enter_execve")
int tracepoint__syscalls_sys_enter_execve(struct trace_sys_enter_execve* ctx)
{
Expand Down Expand Up @@ -93,24 +118,19 @@ int tracepoint__syscalls_sys_enter_execve(struct trace_sys_enter_execve* ctx)
}
#endif

// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
// in case of failure adding the item to the map, send it directly
u64 pid_tgid = bpf_get_current_pid_tgid();
if (bpf_map_update_elem(&execMap, &pid_tgid, data, BPF_ANY) != 0) {

// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
}

return 0;
};

struct trace_sys_enter_execveat {
short common_type;
char common_flags;
char common_preempt_count;
int common_pid;
int __syscall_nr;
char *filename;
const char *const *argv;
const char *const *envp;
int flags;
};
SEC("tracepoint/syscalls/sys_enter_execveat")
int tracepoint__syscalls_sys_enter_execveat(struct trace_sys_enter_execveat* ctx)
{
Expand Down Expand Up @@ -140,10 +160,16 @@ int tracepoint__syscalls_sys_enter_execveat(struct trace_sys_enter_execveat* ctx
data->args_count++;
}

// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
// in case of failure adding the item to the map, send it directly
u64 pid_tgid = bpf_get_current_pid_tgid();
if (bpf_map_update_elem(&execMap, &pid_tgid, data, BPF_ANY) != 0) {

// With some commands, this helper fails with error -28 (ENOSPC). Misleading error? cmd failed maybe?
// BUG: after coming back from suspend state, this helper fails with error -95 (EOPNOTSUPP)
// Possible workaround: count -95 errors, and from userspace reinitialize the streamer if errors >= n-errors
bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, data, sizeof(*data));
}

return 0;
};

Expand Down

0 comments on commit 68c2c8a

Please sign in to comment.