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

fix(ebpf): revise thread stack identification logic #4578

Merged
merged 1 commit into from
Feb 5, 2025
Merged
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
34 changes: 14 additions & 20 deletions pkg/ebpf/c/common/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ statfunc bool vma_is_main_stack(struct vm_area_struct *vma);
statfunc bool vma_is_main_heap(struct vm_area_struct *vma);
statfunc bool vma_is_anon(struct vm_area_struct *vma);
statfunc bool vma_is_golang_heap(struct vm_area_struct *vma);
statfunc bool vma_is_thread_stack(task_info_t *task_info, struct vm_area_struct *vma);
statfunc bool vma_is_vdso(struct vm_area_struct *vma);
statfunc enum vma_type get_vma_type(task_info_t *task_info, struct vm_area_struct *vma);
statfunc enum vma_type get_vma_type(struct vm_area_struct *vma);
statfunc bool address_in_thread_stack(task_info_t *task_info, u64 address);

// FUNCTIONS

Expand Down Expand Up @@ -206,20 +206,6 @@ statfunc bool vma_is_golang_heap(struct vm_area_struct *vma)
(vm_start & GOLANG_ARENA_HINT_MASK) <= GOLANG_ARENA_HINT_MAX;
}

statfunc bool vma_is_thread_stack(task_info_t *task_info, struct vm_area_struct *vma)
{
// Get the stack area for this task
address_range_t *stack = &task_info->stack;
if (stack->start == 0 && stack->end == 0)
// This thread's stack isn't tracked
return false;

// Check if the VMA is **contained** in the thread stack range.
// We don't check exact address range match because a change to the permissions
// of part of the stack VMA will split it into multiple VMAs.
return BPF_CORE_READ(vma, vm_start) >= stack->start && BPF_CORE_READ(vma, vm_end) <= stack->end;
}

statfunc bool vma_is_vdso(struct vm_area_struct *vma)
{
struct vm_special_mapping *special_mapping =
Expand All @@ -233,7 +219,7 @@ statfunc bool vma_is_vdso(struct vm_area_struct *vma)
return strncmp("[vdso]", mapping_name, 7) == 0;
}

statfunc enum vma_type get_vma_type(task_info_t *task_info, struct vm_area_struct *vma)
statfunc enum vma_type get_vma_type(struct vm_area_struct *vma)
{
// The check order is a balance between how expensive the check is and how likely it is to pass

Expand All @@ -250,9 +236,6 @@ statfunc enum vma_type get_vma_type(task_info_t *task_info, struct vm_area_struc
if (vma_is_golang_heap(vma))
return VMA_GOLANG_HEAP;

if (vma_is_thread_stack(task_info, vma))
return VMA_THREAD_STACK;

if (vma_is_vdso(vma))
return VMA_VDSO;

Expand Down Expand Up @@ -286,4 +269,15 @@ statfunc const char *get_vma_type_str(enum vma_type vma_type)
}
}

statfunc bool address_in_thread_stack(task_info_t *task_info, u64 address)
{
// Get the stack area for this task
address_range_t *stack = &task_info->stack;
if (stack->start == 0 && stack->end == 0)
// This thread's stack isn't tracked
return false;

return address >= stack->start && address <= stack->end;
}

#endif
11 changes: 8 additions & 3 deletions pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5365,7 +5365,11 @@ statfunc void check_suspicious_syscall_source(void *ctx, struct pt_regs *regs, u
// This key already exists, no need to submit the same syscall-vma-process combination again
return;

const char *vma_type_str = get_vma_type_str(get_vma_type(p.task_info, vma));
enum vma_type vma_type = get_vma_type(vma);
if (vma_type == VMA_ANON && address_in_thread_stack(p.task_info, ip))
vma_type = VMA_THREAD_STACK;

const char *vma_type_str = get_vma_type_str(vma_type);
unsigned long vma_start = BPF_CORE_READ(vma, vm_start);
unsigned long vma_size = BPF_CORE_READ(vma, vm_end) - vma_start;
unsigned long vma_flags = BPF_CORE_READ(vma, vm_flags);
Expand Down Expand Up @@ -5412,9 +5416,10 @@ statfunc void check_stack_pivot(void *ctx, struct pt_regs *regs, u32 syscall)
// created before tracee started. To avoid false positives, we ignore events
// where the stack pointer's VMA might be a thread stack but it was not
// tracked for this thread. This may result in false negatives.
enum vma_type vma_type = get_vma_type(p.task_info, vma);
enum vma_type vma_type = get_vma_type(vma);
if (vma_type == VMA_MAIN_STACK || vma_type == VMA_GOLANG_HEAP || vma_type == VMA_THREAD_STACK ||
(vma_type == VMA_ANON && !thread_stack_tracked(p.task_info)))
(vma_type == VMA_ANON &&
(!thread_stack_tracked(p.task_info) || address_in_thread_stack(p.task_info, sp))))
return;

const char *vma_type_str = get_vma_type_str(vma_type);
Expand Down