From 095ae59002d2203960d39365ae71cf0e8f1e4bca Mon Sep 17 00:00:00 2001 From: Ofek Shaked Date: Mon, 21 Oct 2024 11:54:07 +0300 Subject: [PATCH] Emit a warning if find_vma is not supported Avoid running the test altogether on unsupported kernels so that the warning doesn't fail the test. --- pkg/ebpf/bpf_log.go | 9 ++++++ pkg/ebpf/c/common/memory.h | 13 ++++++-- pkg/ebpf/c/tracee.bpf.c | 2 +- pkg/ebpf/c/types.h | 3 ++ .../e2e-check_syscall_source.go | 30 ------------------- tests/e2e-inst-test.sh | 6 ++++ 6 files changed, 29 insertions(+), 34 deletions(-) diff --git a/pkg/ebpf/bpf_log.go b/pkg/ebpf/bpf_log.go index e66c53c35f0e..de686eb42f39 100644 --- a/pkg/ebpf/bpf_log.go +++ b/pkg/ebpf/bpf_log.go @@ -31,6 +31,9 @@ const ( // hidden kernel module functions BPFLogIDHidKerMod + + // find vma not supported + BPFLogIDFindVMAUnsupported // BPF_LOG_FIND_VMA_UNSUPPORTED ) var stringMap = map[BPFLogType]string{ @@ -49,6 +52,9 @@ var stringMap = map[BPFLogType]string{ // hidden kernel module functions BPFLogIDHidKerMod: "BPF_LOG_ID_HID_KER_MOD", + + // find vma not supported + BPFLogIDFindVMAUnsupported: "BPF_LOG_FIND_VMA_UNSUPPORTED", } var errorMap = map[BPFLogType]string{ @@ -67,6 +73,9 @@ var errorMap = map[BPFLogType]string{ // hidden kernel module functions BPFLogIDHidKerMod: "Failure in hidden kernel module seeker logic", + + // find vma not supported + BPFLogIDFindVMAUnsupported: "Finding VMAs is not supported in this kernel", } func (b BPFLogType) String() string { diff --git a/pkg/ebpf/c/common/memory.h b/pkg/ebpf/c/common/memory.h index 491617f2a5fe..b287093c7b31 100644 --- a/pkg/ebpf/c/common/memory.h +++ b/pkg/ebpf/c/common/memory.h @@ -15,7 +15,7 @@ statfunc unsigned long get_env_start_from_mm(struct mm_struct *); statfunc unsigned long get_env_end_from_mm(struct mm_struct *); statfunc unsigned long get_vma_flags(struct vm_area_struct *); statfunc unsigned long get_vma_start(struct vm_area_struct *); -statfunc struct vm_area_struct *find_vma(struct task_struct *task, u64 addr); +statfunc struct vm_area_struct *find_vma(void *ctx, struct task_struct *task, u64 addr); statfunc bool vma_is_stack(struct vm_area_struct *vma); statfunc bool vma_is_heap(struct vm_area_struct *vma); statfunc bool vma_is_anon(struct vm_area_struct *vma); @@ -74,8 +74,10 @@ statfunc unsigned long get_vma_start(struct vm_area_struct *vma) */ #define MAX_VMA_RB_TREE_DEPTH 25 +static bool alerted_no_mm_rb = false; + // Given a task, find the first VMA which contains the given address. -statfunc struct vm_area_struct *find_vma(struct task_struct *task, u64 addr) +statfunc struct vm_area_struct *find_vma(void *ctx, struct task_struct *task, u64 addr) { /** * TODO: from kernel version 6.1, the data structure with which VMAs @@ -83,8 +85,13 @@ statfunc struct vm_area_struct *find_vma(struct task_struct *task, u64 addr) * We currently don't support finding VMAs on such systems. */ struct mm_struct *mm = BPF_CORE_READ(task, mm); - if (!bpf_core_field_exists(mm->mm_rb)) + if (!bpf_core_field_exists(mm->mm_rb)) { + if (!alerted_no_mm_rb) { + tracee_log(ctx, BPF_LOG_LVL_WARN, BPF_LOG_FIND_VMA_UNSUPPORTED, 0); + alerted_no_mm_rb = true; + } return NULL; + } // TODO: we don't support NOMMU systems yet (looking up VMAs on them requires walking the VMA // linked list) diff --git a/pkg/ebpf/c/tracee.bpf.c b/pkg/ebpf/c/tracee.bpf.c index bb2c4a27f49b..e6d0c6c535a4 100644 --- a/pkg/ebpf/c/tracee.bpf.c +++ b/pkg/ebpf/c/tracee.bpf.c @@ -5228,7 +5228,7 @@ int BPF_KPROBE(check_syscall_source) struct task_struct *task = (struct task_struct *) bpf_get_current_task(); if (unlikely(task == NULL)) return 0; - struct vm_area_struct *vma = find_vma(task, ip); + struct vm_area_struct *vma = find_vma(ctx, task, ip); if (unlikely(vma == NULL)) return 0; diff --git a/pkg/ebpf/c/types.h b/pkg/ebpf/c/types.h index fe09186288aa..904b5ab3b45b 100644 --- a/pkg/ebpf/c/types.h +++ b/pkg/ebpf/c/types.h @@ -423,6 +423,9 @@ enum bpf_log_id // hidden kernel module functions BPF_LOG_ID_HID_KER_MOD, + + // find vma not supported + BPF_LOG_FIND_VMA_UNSUPPORTED, }; typedef struct bpf_log { diff --git a/tests/e2e-inst-signatures/e2e-check_syscall_source.go b/tests/e2e-inst-signatures/e2e-check_syscall_source.go index 98c06c010850..274adc48035a 100644 --- a/tests/e2e-inst-signatures/e2e-check_syscall_source.go +++ b/tests/e2e-inst-signatures/e2e-check_syscall_source.go @@ -3,8 +3,6 @@ package main import ( "fmt" - libbpfgo "github.com/aquasecurity/libbpfgo/helpers" - "github.com/aquasecurity/tracee/pkg/events" "github.com/aquasecurity/tracee/signatures/helpers" "github.com/aquasecurity/tracee/types/detect" @@ -14,7 +12,6 @@ import ( type e2eCheckSyscallSource struct { cb detect.SignatureHandler - hasMapleTree bool foundStack bool foundHeap bool foundAnonVma bool @@ -23,19 +20,6 @@ type e2eCheckSyscallSource struct { func (sig *e2eCheckSyscallSource) Init(ctx detect.SignatureContext) error { sig.cb = ctx.Callback - // Find if this system uses maple trees to manage VMAs. - // If so we don't expect any check_syscall_source event to be submitted. - ksyms, err := libbpfgo.NewKernelSymbolsMap() - if err != nil { - return err - } - _, err = ksyms.GetSymbolByName("system", "mt_find") - if err != nil { - sig.hasMapleTree = false - } else { - sig.hasMapleTree = true - } - return nil } @@ -53,7 +37,6 @@ func (sig *e2eCheckSyscallSource) GetMetadata() (detect.SignatureMetadata, error func (sig *e2eCheckSyscallSource) GetSelectedEvents() ([]detect.SignatureEventSelector, error) { return []detect.SignatureEventSelector{ {Source: "tracee", Name: "check_syscall_source"}, - {Source: "tracee", Name: "init_namespaces"}, // This event always happens so we can pass the test on unsupported kernels }, nil } @@ -64,19 +47,6 @@ func (sig *e2eCheckSyscallSource) OnEvent(event protocol.Event) error { } switch eventObj.EventName { - case "init_namespaces": - // If the system uses maple trees we won't get any check_syscall_source events, pass the test - if sig.hasMapleTree { - m, _ := sig.GetMetadata() - - sig.cb(&detect.Finding{ - SigMetadata: m, - Event: event, - Data: map[string]interface{}{}, - }) - - return nil - } case "check_syscall_source": syscall, err := helpers.GetTraceeIntArgumentByName(eventObj, "syscall") if err != nil { diff --git a/tests/e2e-inst-test.sh b/tests/e2e-inst-test.sh index 2942f38c3308..5b05bc157c41 100755 --- a/tests/e2e-inst-test.sh +++ b/tests/e2e-inst-test.sh @@ -122,6 +122,12 @@ for TEST in $TESTS; do fi "${TESTS_DIR}"/ftrace_hook.sh ;; + CHECK_SYSCALL_SOURCE) + if cat /proc/kallsyms | grep -qP "trace.*vma_store"; then + info "skip check_syscall_source test on kernel $(uname -r) (VMAs stored in maple tree)" + continue + fi + ;; esac # Run tracee