Skip to content

Commit 8e6f61f

Browse files
committed
feat: Include rootfs in the Exec event
`image` field of the `Exec` event is relative to the root filesystem of the process. That makes it hard to determine the location of the binary if the process is containerized (or, in general, runs inside a mount namespace). That's where the new `rootfs` comes with help. It contains the full path to the root filesystem, which in case of containers has format like: ``` /root/var/lib/docker/btrfs/subvolumes/0991d46b6f686f22f06bddb6948073[...] ``` Using that information, we can still inspect that container layer even when the process (or even container) are not running anymore.
1 parent e53ce43 commit 8e6f61f

File tree

3 files changed

+23
-2
lines changed

3 files changed

+23
-2
lines changed

crates/modules/process-monitor/probes.bpf.c

+17-1
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ struct exec_event
7373
{
7474
uid_t uid;
7575
struct buffer_index filename;
76+
struct buffer_index rootfs;
7677
int argc;
7778
struct buffer_index argv;
7879
struct namespaces namespaces;
@@ -151,6 +152,15 @@ struct
151152
__uint(max_entries, MAX_PENDING_DEAD_PARENTS);
152153
} orphans_map SEC(".maps");
153154

155+
static __always_inline struct path make_mnt_path(struct mount *mnt)
156+
{
157+
struct path mnt_path = {
158+
.dentry = BPF_CORE_READ(mnt, mnt_mountpoint),
159+
.mnt = __builtin_preserve_access_index(&mnt->mnt),
160+
};
161+
return mnt_path;
162+
}
163+
154164
/*
155165
Identifies the container engine and reads the cgroup id of a process
156166
from its `task_struct` into an given array of character.
@@ -316,10 +326,11 @@ int BPF_PROG(sched_process_exec, struct task_struct *p, pid_t old_pid,
316326

317327
u64 uid_gid = bpf_get_current_uid_gid();
318328

329+
struct mnt_namespace *mnt_ns = BPF_CORE_READ(p, nsproxy, mnt_ns);
319330
event->exec.uid = uid_gid;
320331
event->exec.namespaces.uts = BPF_CORE_READ(p, nsproxy, uts_ns, ns.inum);
321332
event->exec.namespaces.ipc = BPF_CORE_READ(p, nsproxy, ipc_ns, ns.inum);
322-
event->exec.namespaces.mnt = BPF_CORE_READ(p, nsproxy, mnt_ns, ns.inum);
333+
event->exec.namespaces.mnt = BPF_CORE_READ(mnt_ns, ns.inum);
323334
event->exec.namespaces.pid = BPF_CORE_READ(p, nsproxy, pid_ns_for_children, ns.inum);
324335
event->exec.namespaces.net = BPF_CORE_READ(p, nsproxy, net_ns, ns.inum);
325336
event->exec.namespaces.time = BPF_CORE_READ(p, nsproxy, time_ns, ns.inum);
@@ -383,6 +394,11 @@ int BPF_PROG(sched_process_exec, struct task_struct *p, pid_t old_pid,
383394
// Check target and whitelist
384395
tracker_check_rules(&GLOBAL_INTEREST_MAP, &m_rules, p, image);
385396

397+
// Rootfs mount is always the first one.
398+
struct mount *root_mnt = BPF_CORE_READ(mnt_ns, root);
399+
struct path mnt_path = make_mnt_path(root_mnt);
400+
get_path_str(&mnt_path, &event->buffer, &event->exec.rootfs);
401+
386402
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
387403
struct mm_struct *mm = BPF_CORE_READ(task, mm);
388404
long start = BPF_CORE_READ(mm, arg_start);

crates/modules/process-monitor/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ pub enum ProcessEvent {
9696
Exec {
9797
uid: Uid,
9898
filename: BufferIndex<str>,
99+
rootfs: BufferIndex<str>,
99100
argc: u32,
100101
argv: BufferIndex<str>, // 0 separated strings
101102
namespaces: Namespaces,
@@ -209,6 +210,7 @@ pub mod pulsar {
209210
ref argv,
210211
namespaces,
211212
ref c_container_id,
213+
..
212214
} => {
213215
let argv =
214216
extract_parameters(argv.bytes(&event.buffer).unwrap_or_else(|err| {
@@ -295,11 +297,13 @@ pub mod pulsar {
295297
},
296298
ProcessEvent::Exec {
297299
filename,
300+
rootfs,
298301
argc,
299302
argv,
300303
..
301304
} => Payload::Exec {
302305
filename: filename.string(&buffer)?,
306+
rootfs: rootfs.string(&buffer)?,
303307
argc: argc as usize,
304308
argv: extract_parameters(argv.bytes(&buffer)?).into(),
305309
},

crates/pulsar-core/src/event.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,7 @@ pub enum Payload {
211211
},
212212
Exec {
213213
filename: String,
214+
rootfs: String,
214215
argc: usize,
215216
argv: Argv,
216217
},
@@ -304,7 +305,7 @@ impl fmt::Display for Payload {
304305
Payload::FileRename { source, destination } => write!(f,"File Rename {{ source: {source}, destination {destination} }}"),
305306
Payload::ElfOpened { filename, flags } => write!(f,"Elf Opened {{ filename: {filename}, flags: {flags} }}"),
306307
Payload::Fork { ppid, uid, gid } => write!(f,"Fork {{ ppid: {ppid} uid: {uid} gid: {gid} }}"),
307-
Payload::Exec { filename, argc, argv } => write!(f,"Exec {{ filename: {filename}, argc: {argc}, argv: {argv} }}"),
308+
Payload::Exec { filename, rootfs, argc, argv } => write!(f,"Exec {{ filename: {filename}, rootfs: {rootfs}, argc: {argc}, argv: {argv} }}"),
308309
Payload::Exit { exit_code } => write!(f,"Exit {{ exit_code: {exit_code} }}"),
309310
Payload::ChangeParent { ppid } => write!(f,"Parent changed {{ ppid: {ppid} }}"),
310311
Payload::CredentialsChange { uid, gid } => write!(f,"Credentials changed {{ uid: {uid} gid: {gid} }}"),

0 commit comments

Comments
 (0)