Skip to content

Commit

Permalink
bpf: read proc exe at tracepoint/sys_execve
Browse files Browse the repository at this point in the history
This is needed for matchBinaries in the next commit. Previously we were
using the tracepoint argugement filename, which is potentially a
relative path.  This change has two main benefits: all paths checked
against matchBinaries will be absolutes and all symbolic links will be
resolved by the kernel.

Signed-off-by: Mahe Tardy <mahe.tardy@gmail.com>
  • Loading branch information
mtardy committed Jan 10, 2024
1 parent 908f4db commit 86cf965
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
3 changes: 3 additions & 0 deletions bpf/lib/bpf_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

/* __d_path_local flags */
// #define UNRESOLVED_MOUNT_POINTS 0x01 // (deprecated)
// this error is returned by __d_path_local in the following cases:
// - the path walk did not conclude (too many dentry)
// - the path was too long to fit in the buffer
#define UNRESOLVED_PATH_COMPONENTS 0x02

#ifdef __LARGE_BPF_PROG
Expand Down
16 changes: 14 additions & 2 deletions bpf/lib/process.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,19 @@ struct msg_k8s {
char docker_id[DOCKER_ID_LENGTH];
}; // All fields aligned so no 'packed' attribute.

#define BINARY_PATH_MAX_LEN 256

struct heap_exe {
// because of verifier limitations, this has to be 2 * 256 bytes while 256
// should be theoretically sufficient, and actually is, in unit tests.
char buf[BINARY_PATH_MAX_LEN * 2];
// offset points to the start of the path in the above buffer. Use offset to
// read the path in the buffer since it's written from the end.
char *off;
__u32 len;
__u32 error;
}; // All fields aligned so no 'packed' attribute.

struct msg_execve_event {
struct msg_common common;
struct msg_k8s kube;
Expand All @@ -289,10 +302,9 @@ struct msg_execve_event {
/* below fields are not part of the event, serve just as
* heap for execve programs
*/
struct heap_exe exe;
}; // All fields aligned so no 'packed' attribute.

#define BINARY_PATH_MAX_LEN 256

// This structure stores the binary path that was recorded on execve.
// Technically PATH_MAX is 4096 but we limit the length we store since we have
// limits on the length of the string to compare:
Expand Down
20 changes: 20 additions & 0 deletions bpf/process/bpf_execve_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,21 @@ read_execve_shared_info(void *ctx, __u64 pid)
return secureexec;
}

static inline __attribute__((always_inline)) __u32
read_exe(struct task_struct *task, struct heap_exe *exe)
{
struct file *file = BPF_CORE_READ(task, mm, exe_file);
struct path *path = __builtin_preserve_access_index(&file->f_path);

exe->len = BINARY_PATH_MAX_LEN;
exe->off = (char *)&exe->buf;
exe->off = __d_path_local(path, exe->off, (int *)&exe->len, (int *)&exe->error);
if (exe->len > 0)
exe->len = BINARY_PATH_MAX_LEN - exe->len;

return exe->len;
}

__attribute__((section("tracepoint/sys_execve"), used)) int
event_execve(struct sched_execve_args *ctx)
{
Expand Down Expand Up @@ -184,6 +199,11 @@ event_execve(struct sched_execve_args *ctx)
p->auid = get_auid();
p->uid = get_current_uid_gid();

// Reading the absolute path of the process exe for matchBinaries.
// Historically we used the filename, a potentially relative path (maybe to
// a symlink) coming from the execve tracepoint.
read_exe(task, &event->exe);

p->size += read_path(ctx, event, filename);
p->size += read_args(ctx, event);
p->size += read_cwd(ctx, p);
Expand Down

0 comments on commit 86cf965

Please # to comment.