falcosecurity / libs

libsinsp, libscap, the kernel module driver, and the eBPF driver sources
https://falcosecurity.github.io/libs/
Apache License 2.0
222 stars 162 forks source link

Execveat's exepath not working properly #543

Closed araujof closed 2 years ago

araujof commented 2 years ago

Describe the bug

In our tests of several versions of the libs between 0.31.1 and 0.32.1 (inclusive), we ~observed that the execveat system call exit is propagating to libsinsp as execve (ev->get_type() returns 293 instead of 331). We also~ noticed that m_exepath is miscalculated, while m_exe is correct. This is observed from live captures with eBPF/kmod drivers and pre-recorded scap file.

How to reproduce it

To reproduce, compile the following code:

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <linux/fs.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>

// Adapted from "Bypass Falco" presentation (Leonardo Di Donato)
// Note: execveat was introduce in Linux kernel v3.19

int main(){
    int dirfd = open("/bin/echo", O_RDONLY);
    const char* pathname = "";
    const char* argv[] = { "echo", "ciao", "ciccio", "pasticcio", "buon", "capriccio", NULL };
    const char* envp[] = { NULL };
    unsigned int flags = AT_EMPTY_PATH;
    int rc = syscall( SYS_execveat, dirfd, pathname, argv, envp, flags);
    printf("errno: %d\n", errno);
}

From the latest release of sysdig (0.29.3):

2108 03:58:54.708899207 16 example (59192.59192) > openat dirfd=-100(AT_FDCWD) name=/bin/echo flags=1(O_RDONLY) mode=0
2109 03:58:54.708915746 16 example (59192.59192) < openat fd=3(<f>/bin/echo) dirfd=-100(AT_FDCWD) name=/bin/echo flags=1(O_RDONLY) mode=0 dev=CA02
2110 03:58:54.708918923 16 example (59192.59192) > execveat dirfd=3(<f>/bin/echo) pathname=(/bin/echo) flags=1(AT_EMPTY_PATH)
2111 03:58:54.709185619 16 3 (59192.59192) < execve res=0 exe=echo args=ciao.ciccio.pasticcio.buon.capriccio. tid=59192(3) pid=59192(3) ptid=76505(bash) cwd= fdlimit=1024 pgft_maj=0 pgft_min=70 vm_size=364 vm_rss=4 vm_swap=0 comm=3 cgroups=cpuset=/.cpu=/user.slice.cpuacct=/user.slice.io=/user.slice.memory=/user.slic... env= tty=34841 pgid=59192(3) loginuid=1002 flags=0```

Printing the values directly from the sinsp event's exit, we get:

type: 293, exepath: /home/<path-to-example-dir>/example exe: echo

Expected behavior

~The event type (as returned by ev->get_type()) should be 331 (denoting execveat) on exit. Also,~ m_exepath should be "/bin/echo" in this example code.

Environment

Andreagit97 commented 2 years ago

Hey @araujof thank you for pointing this out! For what concern the execveat exit event, this is the normal kernel behavior, since execveat is a wrapper of execve, when the call succeeds the event returned is simply an execve exit event. Only in case of syscall failure we can observe an execveat exit event... you can find more information in this PR, where the support for execveat was introduced.

The exepath issue is new to me, so I need to take a closer look at it :eyes: thank you again for having highlighted it!

araujof commented 2 years ago

@Andreagit97 Thanks for getting back to me quickly and pointing to the PR :)

Andreagit97 commented 2 years ago

Ei @araujof this PR https://github.com/falcosecurity/libs/pull/552 should solve the issue, I have added some test cases and it seems to work smooth :)

araujof commented 2 years ago

@Andreagit97 thanks a bunch! We will test.

araujof commented 2 years ago

@Andreagit97 I tested PR #552 with the program example above, and it solves the exepath issue. Below is a SysFlow trace showing the correct exepath's (Cmd field). Thanks!

image