Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions fact-ebpf/src/bpf/bound_path.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,12 @@ __always_inline static struct bound_path_t* _path_read(struct path* path, bound_
return bound_path;
}

__always_inline static struct bound_path_t* path_read_unchecked(struct path* path) {
return _path_read(path, BOUND_PATH_MAIN, true);
__always_inline static struct bound_path_t* path_read_unchecked(struct path* path, bool use_bpf_d_path) {
return _path_read(path, BOUND_PATH_MAIN, use_bpf_d_path);
}

__always_inline static struct bound_path_t* path_read_alt_unchecked(struct path* path, bool use_bpf_d_path) {
return _path_read(path, BOUND_PATH_ALTERNATE, use_bpf_d_path);
}

__always_inline static struct bound_path_t* path_read(struct path* path) {
Expand Down
39 changes: 36 additions & 3 deletions fact-ebpf/src/bpf/events.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ __always_inline static void submit_rename_event(struct submit_event_args_t* args
}

args->event->type = FILE_ACTIVITY_RENAME;
bpf_probe_read_str(args->event->rename.filename, PATH_MAX, old_filename);
inode_copy(&args->event->rename.inode, old_inode);
args->event->rename.monitored = old_monitored;
bpf_probe_read_str(args->event->from.filename, PATH_MAX, old_filename);
inode_copy(&args->event->from.inode, old_inode);
args->event->from.monitored = old_monitored;

__submit_event(args, path_hooks_support_bpf_d_path);
}
Expand Down Expand Up @@ -212,3 +212,36 @@ __always_inline static void submit_acl_event(struct submit_event_args_t* args,
// inode_set_acl does not support bpf_d_path (no struct path available)
__submit_event(args, false);
}

__always_inline static void submit_mount_event(struct submit_event_args_t* args) {
if (!reserve_event(args)) {
return;
}
args->event->type = FILE_ACTIVITY_MOUNT;

__submit_event(args, true);
}

__always_inline static void submit_umount_event(struct submit_event_args_t* args) {
if (!reserve_event(args)) {
return;
}
args->event->type = FILE_ACTIVITY_UMOUNT;

__submit_event(args, true);
}

__always_inline static void submit_move_mount_event(struct submit_event_args_t* args,
const char from_filename[PATH_MAX],
inode_key_t* from_inode,
monitored_t from_monitored) {
if (!reserve_event(args)) {
return;
}
args->event->type = FILE_ACTIVITY_MOVE_MOUNT;
bpf_probe_read_str(args->event->from.filename, PATH_MAX, from_filename);
inode_copy(&args->event->from.inode, from_inode);
args->event->from.monitored = from_monitored;

__submit_event(args, false);
}
109 changes: 108 additions & 1 deletion fact-ebpf/src/bpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ int BPF_PROG(trace_file_open, struct file* file) {
}
}

struct bound_path_t* path = path_read_unchecked(&file->f_path);
struct bound_path_t* path = path_read_unchecked(&file->f_path, true);
if (path == NULL) {
bpf_printk("Failed to read path");
m->file_open.error++;
Expand Down Expand Up @@ -484,3 +484,110 @@ int BPF_PROG(trace_path_rmdir, struct path* dir, struct dentry* dentry) {
submit_rmdir_event(&args);
return 0;
}

SEC("lsm/sb_mount")
int BPF_PROG(trace_sb_mount, const char* dev_name, struct path* path, const char* type, unsigned long flags, void* data) {
struct metrics_t* m = get_metrics();
if (m == NULL) {
return 0;
}
struct submit_event_args_t args = {.metrics = &m->sb_mount};
args.metrics->total++;

struct bound_path_t* bound_path = path_read_unchecked(path, true);
if (bound_path == NULL) {
bpf_printk("Failed to read mount directory");
args.metrics->error++;
return 0;
}
args.filename = bound_path->path;

args.inode = inode_to_key(path->dentry->d_inode);

struct dentry* parent_dentry = BPF_CORE_READ(path, dentry, d_parent);
struct inode* parent_inode_ptr = parent_dentry ? BPF_CORE_READ(parent_dentry, d_inode) : NULL;
args.parent_inode = inode_to_key(parent_inode_ptr);

args.monitored = is_monitored(&args.inode, bound_path, &args.parent_inode);
if (args.monitored == NOT_MONITORED) {
args.metrics->ignored++;
return 0;
}

submit_mount_event(&args);

return 0;
}

SEC("lsm/sb_umount")
int BPF_PROG(trace_sb_umount, struct vfsmount* mnt, int flags) {
struct metrics_t* m = get_metrics();
if (m == NULL) {
return 0;
}
struct submit_event_args_t args = {.metrics = &m->sb_mount};
args.metrics->total++;

struct path p = {.dentry = BPF_CORE_READ(mnt, mnt_root), .mnt = mnt};
struct bound_path_t* bound_path = _path_read(&p, BOUND_PATH_MAIN, false);
if (bound_path == NULL) {
bpf_printk("Failed to read umount directory");
args.metrics->error++;
return 0;
}
args.filename = bound_path->path;

args.inode = inode_to_key(mnt->mnt_root->d_inode);

struct dentry* parent_dentry = BPF_CORE_READ(mnt, mnt_root, d_parent);
struct inode* parent_inode_ptr = parent_dentry ? BPF_CORE_READ(parent_dentry, d_inode) : NULL;
args.parent_inode = inode_to_key(parent_inode_ptr);

args.monitored = is_monitored(&args.inode, bound_path, &args.parent_inode);
if (args.monitored == NOT_MONITORED) {
args.metrics->ignored++;
return 0;
}

submit_umount_event(&args);

return 0;
}

SEC("lsm/move_mount")
int BPF_PROG(trace_move_mount, struct path* from, struct path* to) {
struct metrics_t* m = get_metrics();
if (m == NULL) {
return 0;
}
struct submit_event_args_t args = {.metrics = &m->move_mount};

args.metrics->total++;

struct bound_path_t* to_path = path_read_unchecked(to, false);
if (to_path == NULL) {
bpf_printk("Failed to read to_path");
goto error;
}
args.filename = to_path->path;

struct bound_path_t* from_path = path_read_alt_unchecked(from, false);
if (from_path == NULL) {
bpf_printk("Failed to read from_path");
goto error;
}

args.inode = inode_to_key(to->dentry->d_inode);
args.parent_inode = inode_to_key(to->dentry->d_inode);
args.monitored = is_monitored(&args.inode, to_path, &args.parent_inode);

inode_key_t from_inode = inode_to_key(from->dentry->d_inode);
monitored_t from_monitored = is_monitored(&from_inode, from_path, NULL);

submit_move_mount_event(&args, from_path->path, &from_inode, from_monitored);
return 0;

error:
args.metrics->error++;
return 0;
}
8 changes: 7 additions & 1 deletion fact-ebpf/src/bpf/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ typedef enum file_activity_type_t {
FILE_ACTIVITY_SETXATTR,
FILE_ACTIVITY_REMOVEXATTR,
FILE_ACTIVITY_ACL_SET,
FILE_ACTIVITY_MOUNT,
FILE_ACTIVITY_UMOUNT,
FILE_ACTIVITY_MOVE_MOUNT,
} file_activity_type_t;

struct event_t {
Expand All @@ -140,7 +143,7 @@ struct event_t {
char filename[PATH_MAX];
inode_key_t inode;
monitored_t monitored;
} rename;
} from; // Used by events that have two paths (like rename or move_mount).
struct {
char name[XATTR_NAME_MAX_LEN];
} xattr;
Expand Down Expand Up @@ -194,4 +197,7 @@ struct metrics_t {
struct metrics_by_hook_t inode_setxattr;
struct metrics_by_hook_t inode_removexattr;
struct metrics_by_hook_t inode_set_acl;
struct metrics_by_hook_t sb_mount;
struct metrics_by_hook_t sb_umount;
struct metrics_by_hook_t move_mount;
};
3 changes: 3 additions & 0 deletions fact-ebpf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ impl_metrics_t!(
inode_setxattr,
inode_removexattr,
inode_set_acl,
sb_mount,
sb_umount,
move_mount,
);

unsafe impl Pod for metrics_t {}
Expand Down
Loading
Loading