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): fix insufficiently accurate detection of golang heaps #4550

Merged
Merged
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
17 changes: 13 additions & 4 deletions pkg/ebpf/c/common/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,25 +176,34 @@ statfunc bool vma_is_anon(struct vm_area_struct *vma)
// The golang heap consists of arenas which are memory regions mapped using mmap.
// When allocating areans, golang supplies mmap with an address hint, which is an
// address that the kernel should place the mapping at.
// Hints are constant and vary between architectures, see `mallocinit()` in
// https://github.com/golang/go/blob/master/src/runtime/malloc.go
// Hints for x86_64 begin at 0xc000000000 and for ARM64 at 0x4000000000.
// From observation, when allocating arenas the MAP_FIXED flag is used which forces
// the kernel to use the specified address or fail the mapping, so it is safe to
// rely on the address pattern to determine if it belongs to a heap arena.
#define GOLANG_ARENA_HINT_MASK 0x80ff00000000UL
#define GOLANG_ARENA_HINT_MASK 0xffffffff00000000UL
#if defined(bpf_target_x86)
#define GOLANG_ARENA_HINT (0xc0UL << 32)
#elif defined(bpf_target_arm64)
#define GOLANG_ARENA_HINT (0x40UL << 32)
#else
#error Unsupported architecture
#endif
// We define a max hint that we assume golang allocations will never exceed.
// This translates to the address 0xff00000000.
// This means that we assume that a golang program will never allocate more than
// 256GB of memory on x86_64, or 768GB on ARM64.
#define GOLANG_ARENA_HINT_MAX (0xffUL << 32)

statfunc bool vma_is_golang_heap(struct vm_area_struct *vma)
{
u64 vm_start = BPF_CORE_READ(vma, vm_start);

return (vm_start & GOLANG_ARENA_HINT_MASK) == GOLANG_ARENA_HINT;
// Check if the VMA address is in the range provided by golang heap arena address hints.
// Of course, any program can also allocate memory at these addresses which will result
// in a false positive for this check, so any caller of this function must make sure
// that a false positive for this check is acceptable.
return (vm_start & GOLANG_ARENA_HINT_MASK) >= GOLANG_ARENA_HINT &&
(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)
Expand Down
Loading