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 Jun 5, 2024
1 parent 2c2c067 commit 01399d6
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 7 deletions.
4 changes: 2 additions & 2 deletions pkg/ebpf/c/common/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ statfunc const char *get_device_name(struct device *dev)
#define has_prefix(p, s, n) \
({ \
int rc = 0; \
char *pre = p, *str = s; \
const char *pre = p, *str = s; \
_Pragma("unroll") for (int z = 0; z < n; pre++, str++, z++) \
{ \
if (!*pre) { \
Expand All @@ -49,7 +49,7 @@ statfunc const char *get_device_name(struct device *dev)

#else

static __inline int has_prefix(char *prefix, char *str, int n)
static __inline int has_prefix(const char *prefix, const char *str, int n)
{
int i;
#pragma unroll
Expand Down
12 changes: 12 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,14 @@ 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;

return has_prefix("[vdso]", BPF_CORE_READ(special_mapping, name), 6) == 0;
}

#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 @@ -5117,8 +5117,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 @@ -289,6 +289,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 @@ -299,7 +309,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
2 changes: 1 addition & 1 deletion pkg/ebpf/event_filters.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (t *Tracee) populateEventFilterMaps() error {
eventFilters := map[string]filters.Filter[*filters.StringFilter]{}
for it := t.config.Policies.CreateAllIterator(); it.HasNext(); {
p := it.Next()
f := p.ArgFilter.GetEventFilters(eventID)
f := p.DataFilter.GetEventFilters(eventID)
if len(f) == 0 {
continue
}
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

0 comments on commit 01399d6

Please sign in to comment.