Skip to content

Commit e94e169

Browse files
committed
Attach to the chown LSM hook
Extend the event type with a union of type specific structs.
1 parent 3c44a18 commit e94e169

File tree

5 files changed

+71
-3
lines changed

5 files changed

+71
-3
lines changed

fact-ebpf/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ fn generate_bindings(out_dir: &Path) -> anyhow::Result<()> {
4949
let bindings = bindgen::Builder::default()
5050
.header("src/bpf/types.h")
5151
.derive_default(true)
52+
.impl_debug(true)
5253
.parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
5354
.default_enum_style(bindgen::EnumVariation::NewType {
5455
is_bitfield: false,

fact-ebpf/src/bpf/events.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#include "types.h"
88
#include "vmlinux.h"
99

10-
__always_inline static void submit_event(struct metrics_by_hook_t* m, file_activity_type_t event_type, const char filename[PATH_MAX], struct dentry* dentry) {
10+
__always_inline static void submit_event(struct metrics_by_hook_t* m, file_activity_type_t event_type, const char filename[PATH_MAX], struct dentry* dentry, union event_type_specific* specific) {
1111
struct event_t* event = bpf_ringbuf_reserve(&rb, sizeof(struct event_t), 0);
1212
if (event == NULL) {
1313
m->ringbuffer_full++;
@@ -34,6 +34,10 @@ __always_inline static void submit_event(struct metrics_by_hook_t* m, file_activ
3434
goto error;
3535
}
3636

37+
if (specific != NULL) {
38+
bpf_probe_read_kernel(&event->u, sizeof(event->u), specific);
39+
}
40+
3741
m->added++;
3842
bpf_ringbuf_submit(event, 0);
3943
return;

fact-ebpf/src/bpf/file.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,20 @@ __always_inline static bool is_monitored(struct bound_path_t* path) {
7777
path->len = len;
7878
return res;
7979
}
80+
81+
__always_inline static int get_owner_uid_gid(struct dentry* dentry, unsigned int* uid, unsigned int* gid) {
82+
struct inode* inode;
83+
84+
inode = BPF_CORE_READ(dentry, d_inode);
85+
if (inode == NULL) {
86+
return !0;
87+
}
88+
89+
kuid_t kuid = BPF_CORE_READ(inode, i_uid);
90+
kgid_t kgid = BPF_CORE_READ(inode, i_gid);
91+
92+
*uid = BPF_CORE_READ(&kuid, val);
93+
*gid = BPF_CORE_READ(&kgid, val);
94+
95+
return 0;
96+
}

fact-ebpf/src/bpf/main.c

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ int BPF_PROG(trace_file_open, struct file* file) {
4949
}
5050

5151
struct dentry* d = BPF_CORE_READ(file, f_path.dentry);
52-
submit_event(&m->file_open, event_type, path->path, d);
52+
submit_event(&m->file_open, event_type, path->path, d, NULL);
5353

5454
return 0;
5555

@@ -96,10 +96,46 @@ int BPF_PROG(trace_path_unlink, struct path* dir, struct dentry* dentry) {
9696
return 0;
9797
}
9898

99-
submit_event(&m->path_unlink, FILE_ACTIVITY_UNLINK, path->path, dentry);
99+
submit_event(&m->path_unlink, FILE_ACTIVITY_UNLINK, path->path, dentry, NULL);
100100
return 0;
101101

102102
error:
103103
m->path_unlink.error++;
104104
return 0;
105105
}
106+
107+
SEC("lsm/path_chown")
108+
int BPF_PROG(trace_path_chown, struct path *path, unsigned long long uid, unsigned long long gid) {
109+
struct metrics_t* m = get_metrics();
110+
union event_type_specific specific = { 0 };
111+
struct dentry* dentry;
112+
113+
m->path_chown.total++;
114+
115+
struct bound_path_t* bound_path = path_read(path);
116+
if (bound_path == NULL) {
117+
bpf_printk("Failed to read path");
118+
goto error;
119+
}
120+
121+
if (!is_monitored(bound_path)) {
122+
m->path_chown.ignored++;
123+
return 0;
124+
}
125+
126+
dentry = BPF_CORE_READ(path, dentry);
127+
128+
specific.chown.new_ovner.uid = uid;
129+
specific.chown.new_ovner.gid = gid;
130+
if (get_owner_uid_gid(dentry, &specific.chown.prev_owner.uid, &specific.chown.prev_owner.uid)) {
131+
bpf_printk("Failed to get owner uid/gid");
132+
goto error;
133+
}
134+
135+
submit_event(&m->path_chown, FILE_ACTIVITY_CHOWN, bound_path->path, dentry, &specific);
136+
return 0;
137+
138+
error:
139+
m->path_chown.error++;
140+
return 0;
141+
}

fact-ebpf/src/bpf/types.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ typedef enum file_activity_type_t {
3737
FILE_ACTIVITY_OPEN = 0,
3838
FILE_ACTIVITY_CREATION,
3939
FILE_ACTIVITY_UNLINK,
40+
FILE_ACTIVITY_CHOWN,
4041
} file_activity_type_t;
4142

4243
struct event_t {
@@ -45,6 +46,14 @@ struct event_t {
4546
char filename[PATH_MAX];
4647
char host_file[PATH_MAX];
4748
file_activity_type_t type;
49+
union event_type_specific {
50+
struct {
51+
struct {
52+
unsigned int uid;
53+
unsigned int gid;
54+
} prev_owner, new_ovner;
55+
} chown;
56+
} u;
4857
};
4958

5059
/**
@@ -73,4 +82,5 @@ struct metrics_by_hook_t {
7382
struct metrics_t {
7483
struct metrics_by_hook_t file_open;
7584
struct metrics_by_hook_t path_unlink;
85+
struct metrics_by_hook_t path_chown;
7686
};

0 commit comments

Comments
 (0)