Skip to content

Commit dccc3d9

Browse files
authored
feat(ebpf): use bpf_task_pt_regs when available (#4238)
Tracee's `get_task_pt_regs` function mimics the logic of this helper, but relies on assuming some values defined in the kernel. This commit changes this function to use the helper if it is available. This helper must receive a task_struct with BTF info obtained from `bpf_get_current_task_btf`. From my experimentation, the verifier cannot determine whether a task_struct contains BTF info if it was stored outside of the stack. This means that this function cannot acutally retrieve the registers of any task except for the current one. The function name was changed to reflect this requirement, and it no longer receives a task_struct as a parameter. Thanks @oshaked1 for writing this commit!
1 parent 466975e commit dccc3d9

File tree

4 files changed

+21
-7
lines changed

4 files changed

+21
-7
lines changed

pkg/ebpf/c/common/arch.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ statfunc bool is_x86_compat(struct task_struct *);
1313
statfunc bool is_arm64_compat(struct task_struct *);
1414
statfunc bool is_compat(struct task_struct *);
1515
statfunc int get_syscall_id_from_regs(struct pt_regs *);
16-
statfunc struct pt_regs *get_task_pt_regs(struct task_struct *);
16+
statfunc struct pt_regs *get_current_task_pt_regs(void);
1717
statfunc bool has_syscall_fd_arg(uint);
1818
statfunc uint get_syscall_fd_num_from_arg(uint syscall_id, args_t *);
1919

@@ -58,8 +58,20 @@ statfunc int get_syscall_id_from_regs(struct pt_regs *regs)
5858
return id;
5959
}
6060

61-
statfunc struct pt_regs *get_task_pt_regs(struct task_struct *task)
61+
statfunc struct pt_regs *get_current_task_pt_regs(void)
6262
{
63+
struct task_struct *task;
64+
65+
// Use the bpf_task_pt_regs helper if possible
66+
if (bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_get_current_task_btf) &&
67+
bpf_core_enum_value_exists(enum bpf_func_id, BPF_FUNC_task_pt_regs)) {
68+
task = bpf_get_current_task_btf();
69+
return (struct pt_regs *) bpf_task_pt_regs(task);
70+
}
71+
72+
// Helper not available, extract registers manually
73+
task = (struct task_struct *) bpf_get_current_task();
74+
6375
// THREAD_SIZE here is statistically defined and assumed to work for 4k page sizes.
6476
#if defined(bpf_target_x86)
6577
void *__ptr = BPF_CORE_READ(task, stack) + THREAD_SIZE - TOP_OF_KERNEL_STACK_PADDING;

pkg/ebpf/c/common/context.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ statfunc int init_program_data(program_data_t *p, void *ctx, u32 event_id)
140140
p->event->context.eventid = event_id;
141141
p->event->context.ts = get_current_time_in_ns();
142142
p->event->context.processor_id = (u16) bpf_get_smp_processor_id();
143-
p->event->context.syscall = get_task_syscall_id(p->event->task);
143+
p->event->context.syscall = get_current_task_syscall_id();
144144

145145
u32 host_pid = p->event->context.task.host_pid;
146146
p->proc_info = bpf_map_lookup_elem(&proc_info_map, &host_pid);

pkg/ebpf/c/common/task.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
// PROTOTYPES
1111

1212
statfunc int get_task_flags(struct task_struct *task);
13-
statfunc int get_task_syscall_id(struct task_struct *task);
13+
statfunc int get_current_task_syscall_id(void);
1414
statfunc u32 get_task_mnt_ns_id(struct task_struct *task);
1515
statfunc u32 get_task_pid_ns_for_children_id(struct task_struct *task);
1616
statfunc u32 get_task_pid_ns_id(struct task_struct *task);
@@ -39,13 +39,13 @@ statfunc int get_task_flags(struct task_struct *task)
3939
return BPF_CORE_READ(task, flags);
4040
}
4141

42-
statfunc int get_task_syscall_id(struct task_struct *task)
42+
statfunc int get_current_task_syscall_id(void)
4343
{
4444
// There is no originated syscall in kernel thread context
45-
if (get_task_flags(task) & PF_KTHREAD) {
45+
if (get_task_flags((struct task_struct *) bpf_get_current_task()) & PF_KTHREAD) {
4646
return NO_SYSCALL;
4747
}
48-
struct pt_regs *regs = get_task_pt_regs(task);
48+
struct pt_regs *regs = get_current_task_pt_regs();
4949
return get_syscall_id_from_regs(regs);
5050
}
5151

pkg/ebpf/c/vmlinux.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,9 @@ enum bpf_func_id
684684
BPF_FUNC_sk_storage_get = 107,
685685
BPF_FUNC_ktime_get_boot_ns = 125,
686686
BPF_FUNC_copy_from_user = 148,
687+
BPF_FUNC_get_current_task_btf = 158,
687688
BPF_FUNC_for_each_map_elem = 164,
689+
BPF_FUNC_task_pt_regs = 175,
688690
};
689691

690692
#define MODULE_NAME_LEN (64 - sizeof(unsigned long))

0 commit comments

Comments
 (0)