Skip to content

Commit

Permalink
cleanup(modern): add some comments and clean some code paths
Browse files Browse the repository at this point in the history
Signed-off-by: Andrea Terzolo <[email protected]>
  • Loading branch information
Andreagit97 authored and FedeDP committed Oct 6, 2023
1 parent f97b1ca commit 31a142b
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 34 deletions.
21 changes: 12 additions & 9 deletions driver/modern_bpf/helpers/extract/extract_from_kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ static __always_inline u32 extract__syscall_id(struct pt_regs *regs)
#endif
}

static __always_inline bool extract__32bit_syscall()
static __always_inline bool bpf_in_ia32_syscall()
{
uint32_t status;
uint32_t status = 0;
struct task_struct *task = get_current_task();

#if defined(__TARGET_ARCH_x86)
Expand Down Expand Up @@ -87,7 +87,7 @@ static __always_inline unsigned long extract__syscall_argument(struct pt_regs *r
{
unsigned long arg;
#if defined(__TARGET_ARCH_x86)
if (extract__32bit_syscall())
if (bpf_in_ia32_syscall())
{
switch(idx)
{
Expand Down Expand Up @@ -167,21 +167,24 @@ static __always_inline void extract__network_args(void *argv, int num, struct pt
}
#elif defined(__TARGET_ARCH_x86)
int id = extract__syscall_id(regs);
if(extract__32bit_syscall() && id == __NR_ia32_socketcall)
if(bpf_in_ia32_syscall() && id == __NR_ia32_socketcall)
{
__builtin_memset(argv, 0, sizeof(unsigned long) * num);
// First read all arguments on 32 bits.
u32 args_u32[6] = {};
unsigned long args_pointer = extract__syscall_argument(regs, 1);
for(int i = 0; i < num; i++)
bpf_probe_read_user(args_u32, num * sizeof(u32), (void *)args_pointer);

unsigned long *dst = (unsigned long *)argv;
for (int i = 0; i < num; i++)
{
unsigned long *dst = ((unsigned long *)argv) + i;
bpf_probe_read_user(dst, sizeof(u32), ((u32 *)(args_pointer)) + i);
dst[i] = args_u32[i];
}
return;
}
#endif
unsigned long *dst = (unsigned long *)argv;
for (int i = 0; i < num; i++)
{
unsigned long *dst = (unsigned long *)argv;
dst[i] = extract__syscall_argument(regs, i);
}
}
Expand Down
30 changes: 25 additions & 5 deletions driver/modern_bpf/helpers/interfaces/syscalls_dispatcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@
#include <helpers/base/read_from_task.h>
#include <helpers/extract/extract_from_kernel.h>

static __always_inline bool syscalls_dispatcher__check_32bit_syscalls()
{
return extract__32bit_syscall();
}

static __always_inline bool syscalls_dispatcher__64bit_interesting_syscall(u32 syscall_id)
{
return maps__64bit_interesting_syscall(syscall_id);
Expand Down Expand Up @@ -140,6 +135,31 @@ static __always_inline long convert_network_syscalls(struct pt_regs *regs)
break;
}

/* There are cases in which the socket call code is defined
* but the corresponding syscall code is not.
* For example on s390x machines `SYS_ACCEPT` is defined but
* `__NR_accept` is not. The difference with other drivers is
* that in the modern probe we cannot return the associated event
* instead of the syscall code, so we need to find other workarounds.
*
* Known cases in which the socket call code is defined but
* the corresponding syscall code is not:
*
* ----- s390x
* - `SYS_ACCEPT` is defined but `__NR_accept` is not defined
* -> In this case we return a `__NR_accept4`
*
* ----- x86 with CONFIG_IA32_EMULATION
* - `SYS_ACCEPT` is defined but `__NR_accept` is not defined
* -> In this case we return a `__NR_accept4`
*
* - `SYS_SEND` is defined but `__NR_send` is not defined
* -> In this case we drop the event
*
* - `SYS_RECV` is defined but `__NR_recv` is not defined
* -> In this case we drop the event
*/

// Reset NR_socketcall to send a generic even with correct id
#ifdef __NR_socketcall
return __NR_socketcall;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,31 @@ int BPF_PROG(sys_enter,
{
int socketcall_syscall_id = -1;

#ifdef __NR_socketcall
socketcall_syscall_id = __NR_socketcall;
#endif

if(syscalls_dispatcher__check_32bit_syscalls())
if(bpf_in_ia32_syscall())
{
#if defined(__TARGET_ARCH_x86)
if (syscall_id == __NR_ia32_socketcall)
{
socketcall_syscall_id = __NR_ia32_socketcall;
}
else
{
#if defined(__TARGET_ARCH_x86)
syscall_id = syscalls_dispatcher__convert_ia32_to_64(syscall_id);
// syscalls defined only on 32 bits are dropped here.
if(syscall_id == (u32)-1)
{
return 0;
}
}
#else
// TODO: unsupported
return 0;
return 0;
#endif
}
else
{
#ifdef __NR_socketcall
socketcall_syscall_id = __NR_socketcall;
#endif
}
}

/* we convert it here in this way the syscall will be treated exactly as the original one */
Expand Down
24 changes: 13 additions & 11 deletions driver/modern_bpf/programs/attached/dispatchers/syscall_exit.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,22 @@ int BPF_PROG(sys_exit,
{
int socketcall_syscall_id = -1;

#ifdef __NR_socketcall
socketcall_syscall_id = __NR_socketcall;
#endif

u32 syscall_id = extract__syscall_id(regs);

if(syscalls_dispatcher__check_32bit_syscalls())
if(bpf_in_ia32_syscall())
{
#if defined(__TARGET_ARCH_x86)
if (syscall_id == __NR_ia32_socketcall)
{
socketcall_syscall_id = __NR_ia32_socketcall;
}
else
{
#if defined(__TARGET_ARCH_x86)
/*
* 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
* 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)
{
Expand All @@ -52,11 +48,17 @@ int BPF_PROG(sys_exit,
return 0;
}
}
}
#else
// TODO: unsupported
return 0;
#endif
}
}
else
{
#ifdef __NR_socketcall
socketcall_syscall_id = __NR_socketcall;
#endif
}

/* we convert it here in this way the syscall will be treated exactly as the original one */
Expand Down

0 comments on commit 31a142b

Please sign in to comment.