-
Notifications
You must be signed in to change notification settings - Fork 4
ROX-33198: Instrument inode tracking on file open lsm hook #391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
9cba674
7773d9d
e1bb8f0
ded9eb6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -33,21 +33,21 @@ __always_inline static inode_key_t inode_to_key(struct inode* inode) { | |
| return key; | ||
| } | ||
|
|
||
| unsigned long magic = inode->i_sb->s_magic; | ||
| unsigned long magic = BPF_CORE_READ(inode, i_sb, s_magic); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| switch (magic) { | ||
| case BTRFS_SUPER_MAGIC: | ||
| if (bpf_core_type_exists(struct btrfs_inode)) { | ||
| struct btrfs_inode* btrfs_inode = container_of(inode, struct btrfs_inode, vfs_inode); | ||
| key.inode = inode->i_ino; | ||
| key.inode = BPF_CORE_READ(inode, i_ino); | ||
| key.dev = BPF_CORE_READ(btrfs_inode, root, anon_dev); | ||
| break; | ||
| } | ||
| // If the btrfs_inode does not exist, most likely it is not | ||
| // supported on the system. Fallback to the generic implementation | ||
| // just in case. | ||
| default: | ||
| key.inode = inode->i_ino; | ||
| key.dev = inode->i_sb->s_dev; | ||
| key.inode = BPF_CORE_READ(inode, i_ino); | ||
| key.dev = BPF_CORE_READ(inode, i_sb, s_dev); | ||
| break; | ||
| } | ||
|
|
||
|
|
@@ -65,6 +65,14 @@ __always_inline static inode_value_t* inode_get(struct inode_key_t* inode) { | |
| return bpf_map_lookup_elem(&inode_map, inode); | ||
| } | ||
|
|
||
| __always_inline static long inode_add(struct inode_key_t* inode) { | ||
| if (inode == NULL) { | ||
| return -1; | ||
| } | ||
| inode_value_t value = 0; | ||
| return bpf_map_update_elem(&inode_map, inode, &value, BPF_ANY); | ||
| } | ||
|
|
||
| __always_inline static long inode_remove(struct inode_key_t* inode) { | ||
| if (inode == NULL) { | ||
| return 0; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,11 +47,24 @@ int BPF_PROG(trace_file_open, struct file* file) { | |
| inode_key_t inode_key = inode_to_key(file->f_inode); | ||
| inode_key_t* inode_to_submit = &inode_key; | ||
|
|
||
| // Extract parent inode | ||
| struct dentry* parent_dentry = BPF_CORE_READ(file, f_path.dentry, d_parent); | ||
| struct inode* parent_inode_ptr = parent_dentry ? BPF_CORE_READ(parent_dentry, d_inode) : NULL; | ||
| inode_key_t parent_key = inode_to_key(parent_inode_ptr); | ||
|
|
||
| // For file creation events, check if the parent directory is being | ||
| // monitored. If so, add the new file's inode to the tracked set. | ||
| if (event_type == FILE_ACTIVITY_CREATION) { | ||
| if (inode_is_monitored(inode_get(&parent_key)) == MONITORED) { | ||
| inode_add(&inode_key); | ||
| } | ||
| } | ||
|
Comment on lines
+55
to
+61
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we move some of this logic to |
||
|
|
||
| if (!is_monitored(inode_key, path, &inode_to_submit)) { | ||
| goto ignored; | ||
| } | ||
|
|
||
| submit_open_event(&m->file_open, event_type, path->path, inode_to_submit); | ||
| submit_open_event(&m->file_open, event_type, path->path, inode_to_submit, &parent_key); | ||
|
|
||
| return 0; | ||
|
|
||
|
|
@@ -79,14 +92,19 @@ int BPF_PROG(trace_path_unlink, struct path* dir, struct dentry* dentry) { | |
| inode_key_t inode_key = inode_to_key(dentry->d_inode); | ||
| inode_key_t* inode_to_submit = &inode_key; | ||
|
|
||
| // Extract parent inode from dir parameter | ||
| struct inode* parent_inode = BPF_CORE_READ(dir, dentry, d_inode); | ||
| inode_key_t parent_key = inode_to_key(parent_inode); | ||
|
|
||
| if (!is_monitored(inode_key, path, &inode_to_submit)) { | ||
| m->path_unlink.ignored++; | ||
| return 0; | ||
| } | ||
|
|
||
| submit_unlink_event(&m->path_unlink, | ||
| path->path, | ||
| inode_to_submit); | ||
| inode_to_submit, | ||
| &parent_key); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
@@ -109,6 +127,11 @@ int BPF_PROG(trace_path_chmod, struct path* path, umode_t mode) { | |
| inode_key_t inode_key = inode_to_key(path->dentry->d_inode); | ||
| inode_key_t* inode_to_submit = &inode_key; | ||
|
|
||
| // Extract parent inode | ||
| struct dentry* parent_dentry = BPF_CORE_READ(path, dentry, d_parent); | ||
| struct inode* parent_inode = parent_dentry ? BPF_CORE_READ(parent_dentry, d_inode) : NULL; | ||
| inode_key_t parent_key = inode_to_key(parent_inode); | ||
|
|
||
| if (!is_monitored(inode_key, bound_path, &inode_to_submit)) { | ||
| m->path_chmod.ignored++; | ||
| return 0; | ||
|
|
@@ -118,6 +141,7 @@ int BPF_PROG(trace_path_chmod, struct path* path, umode_t mode) { | |
| submit_mode_event(&m->path_chmod, | ||
| bound_path->path, | ||
| inode_to_submit, | ||
| &parent_key, | ||
| mode, | ||
| old_mode); | ||
|
|
||
|
|
@@ -146,6 +170,11 @@ int BPF_PROG(trace_path_chown, struct path* path, unsigned long long uid, unsign | |
| inode_key_t inode_key = inode_to_key(path->dentry->d_inode); | ||
| inode_key_t* inode_to_submit = &inode_key; | ||
|
|
||
| // Extract parent inode | ||
| struct dentry* parent_dentry = BPF_CORE_READ(path, dentry, d_parent); | ||
| struct inode* parent_inode = parent_dentry ? BPF_CORE_READ(parent_dentry, d_inode) : NULL; | ||
| inode_key_t parent_key = inode_to_key(parent_inode); | ||
|
|
||
| if (!is_monitored(inode_key, bound_path, &inode_to_submit)) { | ||
| m->path_chown.ignored++; | ||
| return 0; | ||
|
|
@@ -158,6 +187,7 @@ int BPF_PROG(trace_path_chown, struct path* path, unsigned long long uid, unsign | |
| submit_ownership_event(&m->path_chown, | ||
| bound_path->path, | ||
| inode_to_submit, | ||
| &parent_key, | ||
| uid, | ||
| gid, | ||
| old_uid, | ||
|
|
@@ -195,6 +225,10 @@ int BPF_PROG(trace_path_rename, struct path* old_dir, | |
| inode_key_t* old_inode_submit = &old_inode; | ||
| inode_key_t* new_inode_submit = &new_inode; | ||
|
|
||
| // Extract new parent inode from new_dir | ||
| struct inode* new_parent_inode = BPF_CORE_READ(new_dir, dentry, d_inode); | ||
| inode_key_t new_parent_key = inode_to_key(new_parent_inode); | ||
|
|
||
| bool old_monitored = is_monitored(old_inode, old_path, &old_inode_submit); | ||
| bool new_monitored = is_monitored(new_inode, new_path, &new_inode_submit); | ||
|
|
||
|
|
@@ -207,7 +241,8 @@ int BPF_PROG(trace_path_rename, struct path* old_dir, | |
| new_path->path, | ||
| old_path->path, | ||
| old_inode_submit, | ||
| new_inode_submit); | ||
| new_inode_submit, | ||
| &new_parent_key); | ||
| return 0; | ||
|
|
||
| error: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parent inode was added to the event so that it could be used to find the parent path. It is added for all event types, not just when a file is opened. Perhaps NULL could be passed instead of the actual parent inode for the other type of events for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, passing
NULLshould be enough for now