Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add security_task_prctl event #4583

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
235 changes: 235 additions & 0 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5296,6 +5296,241 @@ int BPF_KPROBE(trace_chmod_common)
return events_perf_submit(&p, 0);
}

SEC("kprobe/security_task_prctl")
int BPF_KPROBE(trace_security_task_prctl)
{
program_data_t p = {};
if (!init_program_data(&p, ctx, SECURITY_TASK_PRCTL))
return 0;

if (!evaluate_scope_filters(&p))
return 0;

// Save raw args
int option = PT_REGS_PARM1(ctx);
unsigned long arg2 = PT_REGS_PARM2(ctx);
unsigned long arg3 = PT_REGS_PARM3(ctx);
unsigned long arg4 = PT_REGS_PARM4(ctx);
unsigned long arg5 = PT_REGS_PARM5(ctx);
save_to_submit_buf(&p.event->args_buf, &option, sizeof(option), 0);
save_to_submit_buf(&p.event->args_buf, &arg2, sizeof(arg2), 1);
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 2);
save_to_submit_buf(&p.event->args_buf, &arg4, sizeof(arg4), 3);
save_to_submit_buf(&p.event->args_buf, &arg5, sizeof(arg5), 4);

// Save PR_SET_VMA arg
if (option == PR_SET_VMA && arg2 == PR_SET_VMA_ANON_NAME && arg5 != 0)
save_str_to_buf(&p.event->args_buf, (char *) arg5, 5);

// Save PR_SET_MM args
if (option == PR_SET_MM) {
// Save all old mm info regardless of operation
struct mm_struct *mm = get_mm_from_task(p.event->task);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->start_code),
sizeof(mm->start_code),
6);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->end_code),
sizeof(mm->end_code),
7);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->start_data),
sizeof(mm->start_data),
8);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->end_data),
sizeof(mm->end_data),
9);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->start_brk),
sizeof(mm->start_brk),
10);
save_to_submit_buf(
&p.event->args_buf, __builtin_preserve_access_index(&mm->brk), sizeof(mm->brk), 11);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->start_stack),
sizeof(mm->start_stack),
12);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->arg_start),
sizeof(mm->arg_start),
13);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->arg_end),
sizeof(mm->arg_end),
14);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->env_start),
sizeof(mm->env_start),
15);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm->env_end),
sizeof(mm->env_end),
16);
void *saved_auxv;
u32 size;
if (bpf_core_field_exists(mm->saved_auxv)) {
saved_auxv = BPF_CORE_READ(mm, saved_auxv);
size = bpf_core_field_size(mm->saved_auxv);
}
// Red Hat version
else {
struct mm_struct___redhat *mm_redhat = (struct mm_struct___redhat *) mm;
saved_auxv = BPF_CORE_READ(mm_redhat, mm_rh, saved_auxv);
size = bpf_core_field_size(mm_redhat->mm_rh->saved_auxv);
}
save_bytes_to_buf(&p.event->args_buf, saved_auxv, size, 17);

struct file *exe = BPF_CORE_READ(mm, exe_file);
void *exe_path = get_path_str(__builtin_preserve_access_index(&exe->f_path));
dev_t exe_dev = get_dev_from_file(exe);
unsigned long exe_inode = get_inode_nr_from_file(exe);
u64 exe_ctime = get_ctime_nanosec_from_file(exe);
umode_t exe_inode_mode = get_inode_mode_from_file(exe);

save_str_to_buf(&p.event->args_buf, exe_path, 18);
save_to_submit_buf(&p.event->args_buf, &exe_dev, sizeof(exe_dev), 19);
save_to_submit_buf(&p.event->args_buf, &exe_inode, sizeof(exe_inode), 20);
save_to_submit_buf(&p.event->args_buf, &exe_ctime, sizeof(exe_ctime), 21);
save_to_submit_buf(&p.event->args_buf, &exe_inode_mode, sizeof(exe_inode_mode), 22);

struct prctl_mm_map *mm_map;

// Save new mm info according to operation
switch (arg2) {
case PR_SET_MM_START_CODE:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 23);
break;
case PR_SET_MM_END_CODE:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 24);
break;
case PR_SET_MM_START_DATA:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 25);
break;
case PR_SET_MM_END_DATA:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 26);
break;
case PR_SET_MM_START_BRK:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 27);
break;
case PR_SET_MM_BRK:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 28);
break;
case PR_SET_MM_START_STACK:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 29);
break;
case PR_SET_MM_ARG_START:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 30);
break;
case PR_SET_MM_ARG_END:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 31);
break;
case PR_SET_MM_ENV_START:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 32);
break;
case PR_SET_MM_ENV_END:
save_to_submit_buf(&p.event->args_buf, &arg3, sizeof(arg3), 33);
break;
case PR_SET_MM_AUXV:
save_bytes_to_buf(&p.event->args_buf, (void *) arg3, arg4, 34);
break;
case PR_SET_MM_EXE_FILE:
exe = get_struct_file_from_fd(arg3);
exe_path = get_path_str(__builtin_preserve_access_index(&exe->f_path));
exe_dev = get_dev_from_file(exe);
exe_inode = get_inode_nr_from_file(exe);
exe_ctime = get_ctime_nanosec_from_file(exe);
exe_inode_mode = get_inode_mode_from_file(exe);

save_str_to_buf(&p.event->args_buf, exe_path, 35);
save_to_submit_buf(&p.event->args_buf, &exe_dev, sizeof(exe_dev), 36);
save_to_submit_buf(&p.event->args_buf, &exe_inode, sizeof(exe_inode), 37);
save_to_submit_buf(&p.event->args_buf, &exe_ctime, sizeof(exe_ctime), 38);
save_to_submit_buf(&p.event->args_buf, &exe_inode_mode, sizeof(exe_inode_mode), 39);

break;
case PR_SET_MM_MAP:
mm_map = (struct prctl_mm_map *) arg3;
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->start_code),
sizeof(mm_map->start_code),
23);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->end_code),
sizeof(mm_map->end_code),
24);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->start_data),
sizeof(mm_map->start_data),
25);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->end_data),
sizeof(mm_map->end_data),
26);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->start_brk),
sizeof(mm_map->start_brk),
27);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->brk),
sizeof(mm_map->brk),
28);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->start_stack),
sizeof(mm_map->start_stack),
29);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->arg_start),
sizeof(mm_map->arg_start),
30);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->arg_end),
sizeof(mm_map->arg_end),
31);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->env_start),
sizeof(mm_map->env_start),
32);
save_to_submit_buf(&p.event->args_buf,
__builtin_preserve_access_index(&mm_map->env_end),
sizeof(mm_map->env_end),
33);
save_bytes_to_buf(&p.event->args_buf,
BPF_CORE_READ_USER(mm_map, auxv),
BPF_CORE_READ_USER(mm_map, auxv_size),
34);

exe = get_struct_file_from_fd(BPF_CORE_READ_USER(mm_map, exe_fd));
exe_path = get_path_str(__builtin_preserve_access_index(&exe->f_path));
exe_dev = get_dev_from_file(exe);
exe_inode = get_inode_nr_from_file(exe);
exe_ctime = get_ctime_nanosec_from_file(exe);
exe_inode_mode = get_inode_mode_from_file(exe);

save_str_to_buf(&p.event->args_buf, exe_path, 35);
save_to_submit_buf(&p.event->args_buf, &exe_dev, sizeof(exe_dev), 36);
save_to_submit_buf(&p.event->args_buf, &exe_inode, sizeof(exe_inode), 37);
save_to_submit_buf(&p.event->args_buf, &exe_ctime, sizeof(exe_ctime), 38);
save_to_submit_buf(&p.event->args_buf, &exe_inode_mode, sizeof(exe_inode_mode), 39);

break;
default:
// unknown/invalid operation
return 0;
}
}

// Save old securebits for PR_SET_SECUREBITS
if (option == PR_SET_SECUREBITS) {
struct task_struct *task = p.event->task;
unsigned int old_securebits = BPF_CORE_READ(task, cred, securebits);
save_to_submit_buf(&p.event->args_buf, &old_securebits, sizeof(old_securebits), 40);
}

return events_perf_submit(&p, 0);
}

//
// Syscall checkers
//
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/c/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ enum event_id_e
SECURITY_TASK_SETRLIMIT,
SECURITY_SETTIME64,
CHMOD_COMMON,
SECURITY_TASK_PRCTL,
MAX_EVENT_ID,
NO_EVENT_SUBMIT,

Expand Down
40 changes: 32 additions & 8 deletions pkg/ebpf/c/vmlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ struct task_struct {
u64 start_boottime;
u64 real_start_time;
const struct cred *real_cred;
const struct cred *cred;
char comm[16];
struct files_struct *files;
struct nsproxy *nsproxy;
Expand Down Expand Up @@ -699,17 +700,40 @@ struct rb_root {
struct mm_struct {
struct {
struct rb_root mm_rb;
long unsigned int stack_vm;
long unsigned int start_brk;
long unsigned int brk;
long unsigned int start_stack;
long unsigned int arg_start;
long unsigned int arg_end;
long unsigned int env_start;
long unsigned int env_end;
unsigned long stack_vm;
unsigned long start_code;
unsigned long end_code;
unsigned long start_data;
unsigned long end_data;
unsigned long start_brk;
unsigned long brk;
unsigned long start_stack;
unsigned long arg_start;
unsigned long arg_end;
unsigned long env_start;
unsigned long env_end;
unsigned long saved_auxv[0]; // length can be obtained at runtime using bpf_core_file_size()
struct file *exe_file;
};
};

struct prctl_mm_map {
__u64 start_code;
__u64 end_code;
__u64 start_data;
__u64 end_data;
__u64 start_brk;
__u64 brk;
__u64 start_stack;
__u64 arg_start;
__u64 arg_end;
__u64 env_start;
__u64 env_end;
__u64 *auxv;
__u32 auxv_size;
__u32 exe_fd;
};

struct vfsmount {
struct dentry *mnt_root;
};
Expand Down
25 changes: 25 additions & 0 deletions pkg/ebpf/c/vmlinux_flavors.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,31 @@ struct inode___older_v611 {
struct timespec64 __i_ctime;
};

// Red Hat mm_struct variation
struct mm_struct_rh {
unsigned long saved_auxv[0]; // length can be obtained at runtime using bpf_core_file_size()
};

struct mm_struct___redhat {
struct {
unsigned long start_code;
unsigned long end_code;
unsigned long start_data;
unsigned long end_data;
unsigned long start_brk;
unsigned long brk;
unsigned long start_stack;
unsigned long arg_start;
unsigned long arg_end;
unsigned long env_start;
unsigned long env_end;
struct file *exe_file;
};
union {
struct mm_struct_rh *mm_rh;
};
};

///////////////////

#pragma clang attribute pop
Expand Down
20 changes: 20 additions & 0 deletions pkg/ebpf/c/vmlinux_missing.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,4 +266,24 @@ static inline struct inet_sock *inet_sk(const struct sock *sk)
#define IPPROTO_DSTOPTS 60 // IPv6 destination options
#define IPPROTO_MH 135 // IPv6 mobility header

#define PR_SET_SECUREBITS 28
#define PR_SET_MM 35
#define PR_SET_MM_START_CODE 1
#define PR_SET_MM_END_CODE 2
#define PR_SET_MM_START_DATA 3
#define PR_SET_MM_END_DATA 4
#define PR_SET_MM_START_STACK 5
#define PR_SET_MM_START_BRK 6
#define PR_SET_MM_BRK 7
#define PR_SET_MM_ARG_START 8
#define PR_SET_MM_ARG_END 9
#define PR_SET_MM_ENV_START 10
#define PR_SET_MM_ENV_END 11
#define PR_SET_MM_AUXV 12
#define PR_SET_MM_EXE_FILE 13
#define PR_SET_MM_MAP 14
#define PR_SET_MM_MAP_SIZE 15
#define PR_SET_VMA 0x53564d41
#define PR_SET_VMA_ANON_NAME 0

#endif
1 change: 1 addition & 0 deletions pkg/ebpf/probes/probe_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ func NewDefaultProbeGroup(module *bpf.Module, netEnabled bool) (*ProbeGroup, err
Dup3: NewTraceProbe(SyscallEnter, "dup3", "trace_dup3"),
Dup3Ret: NewTraceProbe(SyscallExit, "dup3", "trace_ret_dup3"),
ChmodCommon: NewTraceProbe(KProbe, "chmod_common", "trace_chmod_common"),
SecurityTaskPrctl: NewTraceProbe(KProbe, "security_task_prctl", "trace_security_task_prctl"),

TestUnavailableHook: NewTraceProbe(KProbe, "non_existing_func", "empty_kprobe"),
ExecTest: NewTraceProbe(RawTracepoint, "raw_syscalls:sched_process_exec", "tracepoint__exec_test"),
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/probes/probes.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ const (
Dup3
Dup3Ret
ChmodCommon
SecurityTaskPrctl
)

// Test probe handles
Expand Down
Loading