Skip to content

Commit

Permalink
Bugfix: 32-bit compat program false positive
Browse files Browse the repository at this point in the history
32-bit programs on x86-64 may use a fast syscall method, whose code resides in the VDSO VMA.
This VMA is not  file backed, so it was incorrectly detected as anonymous memory.
  • Loading branch information
oshaked1 committed Oct 10, 2024
1 parent 453e7f8 commit 8a5a70c
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 8 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/IBM/fluent-forward-go v0.2.2
github.com/Masterminds/sprig/v3 v3.2.3
github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca
github.com/aquasecurity/libbpfgo/helpers v0.4.5
github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f
github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20241009193135-0b23713fa9f9
github.com/aquasecurity/tracee/types v0.0.0-20241008181102-d40bc1f81863
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,8 @@ github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVb
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca h1:OPbvwFFvR11c1bgOLhBq1R5Uk3hwUjHW2KfrdyJan9Y=
github.com/aquasecurity/libbpfgo v0.7.0-libbpf-1.4.0.20240729111821-61d531acf4ca/go.mod h1:UpO6kTehEgAGGKR2twztBxvzjTiLiV/cb2xmlYb+TfE=
github.com/aquasecurity/libbpfgo/helpers v0.4.5 h1:eCoLclL3yqv4N9jqGL3T/ckrLPms2r13C4V2xtU75yc=
github.com/aquasecurity/libbpfgo/helpers v0.4.5/go.mod h1:j/TQLmsZpOIdF3CnJODzYngG4yu1YoDCoRMELxkQSSA=
github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f h1:O4UmMQViaaP1wKL1eXe7C6VylwrUmUB5mYM+roqnUZg=
github.com/aquasecurity/tracee/api v0.0.0-20240905132323-d1eaeef6a19f/go.mod h1:Gn6xVkaBkVe1pOQ0++uuHl+lMMClv0TPY8mCQ6j88aA=
github.com/aquasecurity/tracee/signatures/helpers v0.0.0-20241009193135-0b23713fa9f9 h1:sB84YYSDgUAYNSonXeMPweaN6dviCld8UNqcKDn1jBM=
Expand Down
2 changes: 1 addition & 1 deletion pkg/ebpf/c/common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static __inline int has_prefix(char *prefix, char *str, int n)
}

// prefix is too long
return 0;
return 1;
}

#endif
Expand Down
15 changes: 15 additions & 0 deletions pkg/ebpf/c/common/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ statfunc unsigned long get_vma_start(struct vm_area_struct *);
statfunc struct vm_area_struct *find_vma(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);
statfunc bool vma_is_vdso(struct vm_area_struct *vma);

// FUNCTIONS

Expand Down Expand Up @@ -156,4 +158,17 @@ statfunc bool vma_is_anon(struct vm_area_struct *vma)
return BPF_CORE_READ(vma, vm_file) == NULL;
}

statfunc bool vma_is_vdso(struct vm_area_struct *vma)
{
struct vm_special_mapping *special_mapping =
(struct vm_special_mapping *) BPF_CORE_READ(vma, vm_private_data);
if (special_mapping == NULL)
return false;

// read only 6 characters (7 with NULL terminator), enough to compare with "[vdso]"
char mapping_name[7];
bpf_probe_read_str(&mapping_name, 7, BPF_CORE_READ(special_mapping, name));
return has_prefix("[vdso]", mapping_name, 6);
}

#endif
3 changes: 2 additions & 1 deletion pkg/ebpf/c/tracee.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -5202,8 +5202,9 @@ statfunc enum vma_type get_vma_type(struct vm_area_struct *vma)
if (vma_is_heap(vma))
return VMA_HEAP;

if (vma_is_anon(vma))
if (vma_is_anon(vma) && !vma_is_vdso(vma)) {
return VMA_ANON;
}

return VMA_OTHER;
}
Expand Down
12 changes: 12 additions & 0 deletions pkg/ebpf/c/vmlinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,16 @@ struct rb_node {
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));

struct vm_area_struct;

struct vm_operations_struct {
const char *(*name)(struct vm_area_struct *vma);
};

struct vm_special_mapping {
const char *name;
};

struct vm_area_struct {
union {
struct {
Expand All @@ -301,7 +311,9 @@ struct vm_area_struct {
struct rb_node vm_rb;
struct mm_struct *vm_mm;
long unsigned int vm_flags;
const struct vm_operations_struct *vm_ops;
struct file *vm_file;
void *vm_private_data;
};

typedef unsigned int __kernel_gid32_t;
Expand Down
5 changes: 2 additions & 3 deletions pkg/ebpf/initialization/kconfig.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package initialization

import (
"github.com/aquasecurity/libbpfgo/helpers"
"github.com/aquasecurity/tracee/pkg/errfmt"
"github.com/aquasecurity/tracee/pkg/logger"
"github.com/aquasecurity/tracee/pkg/utils/environment"
Expand All @@ -11,7 +10,7 @@ import (
// Add here all kconfig variables used within tracee.bpf.c
const (
CONFIG_ARCH_HAS_SYSCALL_WRAPPER environment.KernelConfigOption = iota + environment.CUSTOM_OPTION_START
CONFIG_MMU helpers.KernelConfigOption = iota + helpers.CUSTOM_OPTION_START
CONFIG_MMU environment.KernelConfigOption = iota + environment.CUSTOM_OPTION_START
)

var kconfigUsed = map[environment.KernelConfigOption]string{
Expand All @@ -36,7 +35,7 @@ func LoadKconfigValues(kc *environment.KernelConfig) (map[environment.KernelConf
values[key] = environment.UNDEFINED
}
values[CONFIG_ARCH_HAS_SYSCALL_WRAPPER] = environment.BUILTIN // assume CONFIG_ARCH_HAS_SYSCALL_WRAPPER is a BUILTIN option
values[CONFIG_MMU] = helpers.BUILTIN // assume CONFIG_MMU is a BUILTIN option
values[CONFIG_MMU] = environment.BUILTIN // assume CONFIG_MMU is a BUILTIN option
} else {
for key := range kconfigUsed {
values[key] = kc.GetValue(key) // undefined, builtin OR module
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e-inst-signatures/e2e-check_syscall_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package main
import (
"fmt"

libbfgo "github.com/aquasecurity/libbpfgo/helpers"
libbpfgo "github.com/aquasecurity/libbpfgo/helpers"

"github.com/aquasecurity/tracee/pkg/events"
"github.com/aquasecurity/tracee/signatures/helpers"
Expand All @@ -25,11 +25,11 @@ func (sig *e2eCheckSyscallSource) Init(ctx detect.SignatureContext) error {

// 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 := libbfgo.NewKernelSymbolTable()
ksyms, err := libbpfgo.NewKernelSymbolsMap()
if err != nil {
return err
}
_, err = ksyms.GetSymbolByName("mt_find")
_, err = ksyms.GetSymbolByName("system", "mt_find")
if err != nil {
sig.hasMapleTree = false
} else {
Expand Down

0 comments on commit 8a5a70c

Please sign in to comment.