8000 feat(events): create access_remote_vm event by AlonZivony · Pull Request #3551 · aquasecurity/tracee · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

feat(events): create access_remote_vm event #3551

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

Closed
Closed
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
2 changes: 2 additions & 0 deletions .github/workflows/pr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ env:
PROCTREE_DATA_SOURCE
DNS_DATA_SOURCE
WRITABLE_DATA_SOURCE
ACCESS_REMOTE_VM
jobs:
#
# DOC VERIFICATION
Expand Down Expand Up @@ -326,6 +327,7 @@ jobs:
- generate-matrix
runs-on: "github-self-hosted_ami-${{ matrix.ami }}_${{ github.event.number }}-${{ github.run_id }}_${{ matrix.sufix }}"
strategy:
fail-fast: false
matrix:
include: ${{fromJson(needs.generate-matrix.outputs.matrix01)}}
env:
Expand Down
34 changes: 34 additions & 0 deletions docs/docs/events/builtin/extra/access_remote_vm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# access_remote_vm

## Intro
access_remote_vm - gain access to the virtual memory of a separate process through the use of the procfs mem file.

## Description
This event marks access attempt of a process to the virtual memory of another process using the procfs mem file associated with that specific process (/proc/<pid>/mem).
It is a more elaborated event than the `security_file_open` of the mem file.

## Arguments
* `remote_pid`: `int`[K] - PID of the process the memory area belongs to.
* `start_address`: `void *`[K] - Start address of the operation.
* `gup_flags`: `unsigned int`[K] - Flags for get_user_pages operation.
* `vm_flags`: `unsigned long`[K] - Virtual memory flags.
* `mapped.path`: `const char*`[K] - Path of the mapped file, or the name of memory area if no file is mapped.
* `mapped.device_id`: `dev_t`[K,OPT] - Device ID of the mapped file.
* `mapped.inode_number`: `unsigned long`[K,OPT] - Inode number of the mapped file.
* `mapped.ctime`: `unsigned long`[K,OPT] - Creation time of the mapped file.

## Hooks
### get_user_pages_remote
#### Type
kprobe + kretprobe
#### Purpose
The main function that implements the access to the virtual memory area of the other process.

### generic_access_phys
#### Type
kprobe
#### Purpose
A fallback function, implementing the `access` method of the `vma_operations` struct for most of the vmas. It is used to access special memory areas.

## Related Events
`security_file_open`,`security_mmap_file`,`vfs_write`,`vfs_writev`,`vfs_read`,`vfs_readv`
2 changes: 1 addition & 1 deletion go.mod
ED4F
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require (
github.com/IBM/fluent-forward-go v0.2.1
github.com/Masterminds/sprig/v3 v3.2.3
github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231123142329-37c4b843a539
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231127142843-5e798c565c08
github.com/aquasecurity/tracee/api v0.0.0-20231222010915-0f73aad36da9
github.com/aquasecurity/tracee/types v0.0.0-20231231104405-a33891f29d17
github.com/containerd/containerd v1.7.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3 h1:mhDe1mAZR80LjnsCnteS+R2/Ee
github.com/aquasecurity/libbpfgo v0.6.0-libbpf-1.3/go.mod h1:0rEApF1YBHGuZ4C8OYI9q5oDBVpgqtRqYATePl9mCDk=
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231123142329-37c4b843a539 h1:axIHZ3la2/wcqMYO9TUyKO/lMGYizEKyNIodbwQBOkE=
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231123142329-37c4b843a539/go.mod h1:1fGKke5pgH4xYvZ7HqDbLSi/R5zfRFH2K+c9kLp9L34=
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231127142843-5e798c565c08 h1:hlnYuC6sWi3yYi9HNsHLemDfbf6F787GCAkP7kwnqBc=
github.com/aquasecurity/libbpfgo/helpers v0.4.6-0.20231127142843-5e798c565c08/go.mod h1:1fGKke5pgH4xYvZ7HqDbLSi/R5zfRFH2K+c9kLp9L34=
github.com/aquasecurity/tracee/api v0.0.0-20231222010915-0f73aad36da9 h1:1y+/rhVRNZK8s/ZyqXhtqjVLbKs/F9jPjBUn9jcujQs=
github.com/aquasecurity/tracee/api v0.0.0-20231222010915-0f73aad36da9/go.mod h1:QJG2PABXucOsFVO85tQsKxV4c1GUhcjww/Kw+Wv7Y/c=
github.com/aquasecurity/tracee/types v0.0.0-20231231104405-a33891f29d17 h1:tgcl7BuyBLDng+47KKhyOB9gdsq3V9dKoapNyRDchwg=
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/initialize/callbacks.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var (
// 3. %s = check_map_func_compatibility (function name)
// 4. %x = offset (ignored in this check)
// 5. %s = No such file or directory
libbpfgoKprobePerfEventRegexp = regexp.MustCompile(`libbpf:.*prog '(?:trace_check_map_func_compatibility|trace_utimes_common)'.*failed to create kprobe.*perf event: No such file or directory`)
libbpfgoKprobePerfEventRegexp = regexp.MustCompile(`libbpf:.*prog '(?:trace_check_map_func_compatibility|trace_utimes_common|trace_generic_access_phys)'.*failed to create kprobe.*perf event: No such file or directory`)

// triggered by: libbpf/src/libbpf.c->bpf_program__attach_fd()
// "libbpf: prog '%s': failed to attach to %s: %s\n"
Expand Down
1 change: 1 addition & 0 deletions pkg/ebpf/c/common/arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ statfunc int load_args(args_t *args, u32 event_id)
args->args[3] = saved_args->args[3];
args->args[4] = saved_args->args[4];
args->args[5] = saved_args->args[5];
args->args[6] = saved_args->args[6];

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions pkg/ebpf/c/common/consts.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#define MAX_SYS_CALL_TABLE_SIZE 500
#define MAX_MEM_DUMP_SIZE 127

#define MAX_VMA_ITERATIONS 20


#define MAX_STR_ARR_ELEM 38 // TODO: turn this into global variables set w/ libbpfgo
#define MAX_ARGS_STR_ARR_ELEM 15
Expand Down
75 changes: 75 additions & 0 deletions pkg/ebpf/c/common/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vmlinux.h>

#include <common/common.h>
#include <common/ksymbols.h>

// PROTOTYPES

Expand All @@ -12,7 +13,11 @@ statfunc unsigned long get_arg_start_from_mm(struct mm_struct *);
statfunc unsigned long get_arg_end_from_mm(struct mm_struct *);
statfunc unsigned long get_env_start_from_mm(struct mm_struct *);
statfunc unsigned long get_env_end_from_mm(struct mm_struct *);
statfunc struct task_struct *get_owner_task_from_mm(struct mm_struct *);
statfunc struct file *get_mapped_file_from_vma(struct vm_area_struct *);
statfunc struct mount *real_mount(struct vfsmount *);
statfunc unsigned long get_vma_flags(struct vm_area_struct *);
statfunc int get_vma_location(struct vm_area_struct *, size_t, char *);

// FUNCTIONS

Expand Down Expand Up @@ -41,6 +46,16 @@ statfunc unsigned long get_env_end_from_mm(struct mm_struct *mm)
return BPF_CORE_READ(mm, env_end);
}

statfunc struct task_struct *get_owner_task_from_mm(struct mm_struct *mm)
{
return BPF_CORE_READ(mm, owner);
}

statfunc struct file *get_mapped_file_from_vma(struct vm_area_struct *vma)
{
return BPF_CORE_READ(vma, vm_file);
}

statfunc unsigned long get_vma_flags(struct vm_area_struct *vma)
{
return BPF_CORE_READ(vma, vm_flags);
Expand All @@ -51,4 +66,64 @@ statfunc struct mount *real_mount(struct vfsmount *mnt)
return container_of(mnt, struct mount, mnt);
}

// NOTE: The function below use "special_mapping_vmops" and "legacy_special_mapping_vmops"
// symbols. Ensure these symbols are available when invoking this function.

// Returns true if the specified Virtual Memory Area (VMA) is a special mapping, such as
// [vdso]. Returns false otherwise.
statfunc bool is_special_mapping(struct vm_area_struct *vma)
{
char special_mapping_vmops_symbol[22] = "special_mapping_vmops";
char legacy_special_mapping_vmops_symbol[29] = "legacy_special_mapping_vmops";

void *special_mapping_vmops_addr = get_symbol_addr(special_mapping_vmops_symbol);
void *legacy_special_mapping_vmops_addr = get_symbol_addr(legacy_special_mapping_vmops_symbol);

const struct vm_operations_struct *vm_ops = BPF_CORE_READ(vma, vm_ops);

if (!vm_ops)
return false;

if (vm_ops == special_mapping_vmops_addr || vm_ops == legacy_special_mapping_vmops_addr)
return true;

return false;
}

// Returns the descriptive name of the specified Virtual Memory Area (VMA). This function
// identifies special VMAs like [stack], [heap], and [vdso]. It does not resolve VMAs
// mapped to files; such VMAs require alternative methods for detail retrieval.
statfunc int get_vma_location(struct vm_area_struct *vma, size_t max_len, char *location)
{
// Avoid buffer overflow and satisfy the verifier.
if (max_len < 7) {
return 0;
}

struct mm_struct *vm_mm = BPF_CORE_READ(vma, vm_mm);

if (vm_mm) {
u64 start_stack = BPF_CORE_READ(vm_mm, start_stack);
u64 start_brk = BPF_CORE_READ(vm_mm, start_brk);
u64 brk = BPF_CORE_READ(vm_mm, brk);
u64 vm_start = BPF_CORE_READ(vma, vm_start);
u64 vm_end = BPF_CORE_READ(vma, vm_end);

if (vm_start <= start_stack && vm_end >= start_stack) {
__builtin_memcpy(location, "[stack]", 7);

} else if (vm_start <= brk && vm_end >= start_brk) {
__builtin_memcpy(location, "[heap]", 6);

} else if (is_special_mapping(vma)) {
struct vm_special_mapping *special_mapping = BPF_CORE_READ(vma, vm_private_data);
const char *name = BPF_CORE_READ(special_mapping, name);
if (name)
bpf_probe_read_str(location, max_len, name);
}
}

return 0;
}

#endif
16 changes: 16 additions & 0 deletions pkg/ebpf/c/common/probes.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@
#include <common/context.h>
#include <common/filtering.h>

#if defined(bpf_target_x86)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmacro-redefined"
// Redefine the PT_REGS_PARM7 from __unsupported__ to use the stack to get the argument
#define PT_REGS_PARM7(ctx) \
({ \
unsigned long __reg; \
unsigned long *__sp = (unsigned long *) PT_REGS_SP(ctx); \
bpf_core_read(&__reg, sizeof(unsigned long), __sp + 1); \
__reg; \
})
#pragma GCC diagnostic pop

#endif // bpf_target_x86

#define TRACE_ENT_FUNC(name, id) \
int trace_##name(struct pt_regs *ctx) \
{ \
Expand All @@ -27,6 +42,7 @@
args.args[3] = PT_REGS_PARM4(ctx); \
args.args[4] = PT_REGS_PARM5(ctx); \
args.args[5] = PT_REGS_PARM6(ctx); \
args.args[6] = PT_REGS_PARM7(ctx); \
\
return save_args(&args, id); \
}
Expand Down
Loading
Loading
0