From 79990c2669a83d4ab51ff2d7964b326e3cccd299 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Wed, 12 Jul 2023 09:20:25 +0200 Subject: [PATCH] fix(driver): implemented execve and execveat logic to bpf and modern bpf too. A 64bit process that execve's to a 32bit one (eg: a bash shell that executes a 32bit executable), will receive the execve exit event as 64bit event, even if the compat flag is already set on the task. Signed-off-by: Federico Di Pierro --- driver/bpf/probe.c | 21 +++++++++++++++---- driver/main.c | 5 ++++- .../attached/dispatchers/syscall_exit.bpf.c | 18 +++++++++++++--- 3 files changed, 36 insertions(+), 8 deletions(-) diff --git a/driver/bpf/probe.c b/driver/bpf/probe.c index 9a0e0e893b..486929f82e 100644 --- a/driver/bpf/probe.c +++ b/driver/bpf/probe.c @@ -118,11 +118,24 @@ BPF_PROBE("raw_syscalls/", sys_exit, sys_exit_args) if (bpf_in_ia32_syscall()) { -#ifdef CONFIG_X86_64 - id = convert_ia32_to_64(id); - if(id == 0) +#if defined(CONFIG_X86_64) && defined(CONFIG_IA32_EMULATION) + /* + * When a process does execve from 64bit to 32bit, TS_COMPAT is marked true + * but the id of the syscall is __NR_execve, so to correctly parse it we need to + * use 64bit syscall table. On 32bit __NR_execve is equal to __NR_ia32_oldolduname + * which is a very old syscall, not used anymore by most applications + */ +#ifdef __NR_execveat + if (id != __NR_execve && id != __NR_execveat) +#else + if (id != __NR_execve) +#endif { - return 0; + id = convert_ia32_to_64(id); + if(id == 0) + { + return 0; + } } #else // TODO: unsupported diff --git a/driver/main.c b/driver/main.c index 319b06e9d8..7a38080999 100644 --- a/driver/main.c +++ b/driver/main.c @@ -2319,13 +2319,16 @@ TRACEPOINT_PROBE(syscall_exit_probe, struct pt_regs *regs, long ret) { #if defined(CONFIG_X86_64) && defined(CONFIG_IA32_EMULATION) /* - * TODO: do we need to add execveat too? * When a process does execve from 64bit to 32bit, TS_COMPAT is marked true * but the id of the syscall is __NR_execve, so to correctly parse it we need to * use 64bit syscall table. On 32bit __NR_execve is equal to __NR_ia32_oldolduname * which is a very old syscall, not used anymore by most applications */ +#ifdef __NR_execveat + if (event_data.event_info.syscall_data.id != __NR_execve && event_data.event_info.syscall_data.id != __NR_execveat) +#else if (event_data.event_info.syscall_data.id != __NR_execve) +#endif { event_data.event_info.syscall_data.id = g_ia32_64_map[event_data.event_info.syscall_data.id]; diff --git a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c index 66bee9374a..cf7f3d1dff 100644 --- a/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c +++ b/driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c @@ -9,6 +9,9 @@ #include #include +#define X86_64_NR_EXECVE 59 +#define X86_64_NR_EXECVEAT 322 + /* From linux tree: /include/trace/events/syscall.h * TP_PROTO(struct pt_regs *regs, long ret), */ @@ -22,10 +25,19 @@ int BPF_PROG(sys_exit, if(syscalls_dispatcher__check_32bit_syscalls()) { #if defined(__TARGET_ARCH_x86) - syscall_id = syscalls_dispatcher__convert_ia32_to_64(syscall_id); - if(syscall_id == 0) + /* + * When a process does execve from 64bit to 32bit, TS_COMPAT is marked true + * but the id of the syscall is __NR_execve, so to correctly parse it we need to + * use 64bit syscall table. On 32bit __NR_execve is equal to __NR_ia32_oldolduname + * which is a very old syscall, not used anymore by most applications + */ + if (syscall_id != X86_64_NR_EXECVE && syscall_id != X86_64_NR_EXECVEAT) { - return 0; + syscall_id = syscalls_dispatcher__convert_ia32_to_64(syscall_id); + if(syscall_id == 0) + { + return 0; + } } #else // TODO: unsupported