3#include <bpf/bpf_helpers.h>
4#include <bpf/bpf_core_read.h>
5#include <bpf/bpf_tracing.h>
12#define ATTR_MODE (1U << 0)
13#define ATTR_UID (1U << 1)
14#define ATTR_GID (1U << 2)
17#define S_ISUID 0004000
18#define S_ISGID 0002000
21#define S_IWGRP 0000020
22#define S_IWOTH 0000002
25#define S_IRUSR 0000400
26#define S_IWUSR 0000200
29char LICENSE[]
SEC(
"license") =
"GPL";
37#ifndef ROOTGUARD_VMLINUX_HAS_BPF_PATH_D_PATH
39 size_t buf__sz) __weak __ksym;
43 __uint(type, BPF_MAP_TYPE_RINGBUF);
44 __uint(max_entries, 1 << 22);
49 __uint(type, BPF_MAP_TYPE_HASH);
53} auth_tokens
SEC(
".maps");
56 __uint(type, BPF_MAP_TYPE_ARRAY);
60} rg_config_map
SEC(
".maps");
64 __uint(type, BPF_MAP_TYPE_HASH);
68} trusted_execs
SEC(
".maps");
71 __uint(type, BPF_MAP_TYPE_HASH);
75} denied_execs
SEC(
".maps");
79 __uint(type, BPF_MAP_TYPE_HASH);
83} protected_inodes
SEC(
".maps");
142 __uint(type, BPF_MAP_TYPE_HASH);
143 __uint(max_entries, 32768);
146} metadata_domain_states
SEC(
".maps");
148#define RG_METADATA_DECISION_SAMPLE (1U << 0)
149#define RG_METADATA_DECISION_BURST (1U << 1)
156 __uint(type, BPF_MAP_TYPE_LRU_HASH);
157 __uint(max_entries, 65536);
160} exec_contexts
SEC(
".maps");
167 __uint(type, BPF_MAP_TYPE_LRU_HASH);
168 __uint(max_entries, 16384);
171} pending_paths
SEC(
".maps");
180 __uint(type, BPF_MAP_TYPE_LRU_HASH);
181 __uint(max_entries, 65536);
184} task_states
SEC(
".maps");
186static __always_inline __u32
cred_uid(
const struct cred *cred)
193 BPF_CORE_READ_INTO(&uid, cred, uid);
197static __always_inline __u32
cred_euid(
const struct cred *cred)
204 BPF_CORE_READ_INTO(&euid, cred, euid);
210 struct task_struct *task =
211 (
struct task_struct *)bpf_get_current_task_btf();
213 return BPF_CORE_READ(task, cred);
221static __always_inline
void current_ids(__u32 *pid, __u32 *tgid, __u32 *ppid)
223 __u64
id = bpf_get_current_pid_tgid();
224 struct task_struct *task = (
struct task_struct *)bpf_get_current_task_btf();
225 struct task_struct *parent = BPF_CORE_READ(task, real_parent);
228 *tgid = (__u32)(
id >> 32);
229 *ppid = parent ? (__u32)BPF_CORE_READ(parent, tgid) : 0;
235 return bpf_map_lookup_elem(&rg_config_map, &key);
256 __u64 now, window_ns, cooldown_ns;
257 __u32 monitor_global, detect_bursts, sample_limit, burst_threshold;
272 if (!monitor_global && !detect_bursts)
275 key.
cgroup_id = bpf_get_current_cgroup_id();
277 key.
tgid_fallback = (__u32)(bpf_get_current_pid_tgid() >> 32);
279 now = bpf_ktime_get_ns();
281 window_ns = 5000000000ULL;
282 if (cooldown_ns < window_ns)
283 cooldown_ns = window_ns;
285 state = bpf_map_lookup_elem(&metadata_domain_states, &key);
288 bpf_map_update_elem(&metadata_domain_states, &key, &initial, BPF_NOEXIST);
289 state = bpf_map_lookup_elem(&metadata_domain_states, &key);
295 bpf_spin_lock(&state->
lock);
304 if (request_sample && monitor_global &&
310 if (count_burst_candidate && detect_bursts) {
323 bpf_spin_unlock(&state->
lock);
336 asm volatile(
"" :::
"memory");
346 struct super_block *superblock;
351 superblock = BPF_CORE_READ(inode, i_sb);
355 key->
inode = BPF_CORE_READ(inode, i_ino);
356 key->
device = BPF_CORE_READ(superblock, s_dev);
357 return key->
inode != 0;
368 inode = BPF_CORE_READ(file, f_inode);
380 inode = BPF_CORE_READ(dentry, d_inode);
388 return (
const char *)BPF_CORE_READ(dentry, d_name.name);
393 struct task_struct *task;
394 struct mm_struct *mm;
397 task = (
struct task_struct *)bpf_get_current_task_btf();
398 mm = BPF_CORE_READ(task, mm);
402 file = BPF_CORE_READ(mm, exe_file);
408 struct task_struct *task, *parent;
409 struct mm_struct *mm;
414 task = (
struct task_struct *)bpf_get_current_task_btf();
417 parent = BPF_CORE_READ(task, real_parent);
420 mm = BPF_CORE_READ(parent, mm);
423 file = BPF_CORE_READ(mm, exe_file);
430 return left && right &&
439 if (!destination || !source || size == 0)
444 __builtin_memcpy_inline(destination, source,
RG_COMM_LEN);
451 struct task_struct *task;
452 const char *filename;
459 ids = bpf_get_current_pid_tgid();
460 tgid = (__u32)(ids >> 32);
467 task = (
struct task_struct *)bpf_get_current_task_btf();
476 filename = BPF_CORE_READ(bprm, filename);
481 bpf_map_update_elem(&exec_contexts, &tgid, &context, BPF_ANY);
490 return path[0] ==
'/' && path[1] ==
'r' && path[2] ==
'u' &&
491 path[3] ==
'n' && (path[4] ==
'\0' || path[4] ==
'/');
497 __u64 ids = bpf_get_current_pid_tgid();
499 bpf_map_lookup_elem(&pending_paths, &ids);
509 __u64 ids = bpf_get_current_pid_tgid();
510 bpf_map_delete_elem(&pending_paths, &ids);
528 sizeof(pending.
path)) <= 0)
532 ids = bpf_get_current_pid_tgid();
533 bpf_map_update_elem(&pending_paths, &ids, &pending, BPF_ANY);
537 const struct rg_file_key *file_key,
char *destination,
538 __u32 *path_resolution)
540 __u64 ids = bpf_get_current_pid_tgid();
542 bpf_map_lookup_elem(&pending_paths, &ids);
548 bpf_map_delete_elem(&pending_paths, &ids);
554 bpf_map_delete_elem(&pending_paths, &ids);
560 struct task_struct *task;
561 struct task_struct *parent;
574 task = (
struct task_struct *)bpf_get_current_task_btf();
576 event->actor_start_boottime_ns =
577 BPF_CORE_READ(task, start_boottime);
578 parent = BPF_CORE_READ(task, real_parent);
585 context = bpf_map_lookup_elem(&exec_contexts, &tgid);
595 if (event->
ppid == 0)
597 parent_context = bpf_map_lookup_elem(&exec_contexts, &event->
ppid);
600 event->parent_file = parent_context->
executable;
606static __always_inline __u64
task_key(
const struct task_struct *task)
608 return (__u64)(
unsigned long)task;
612 __u32 uid, __u32 euid)
622 existing = bpf_map_lookup_elem(&task_states, &key);
643 bpf_map_update_elem(&task_states, &key, &state, BPF_ANY);
649 bpf_map_update_elem(&task_states, &key, &state, BPF_ANY);
654 struct task_struct *task =
655 (
struct task_struct *)bpf_get_current_task_btf();
661 struct task_struct *task =
662 (
struct task_struct *)bpf_get_current_task_btf();
666 bpf_map_lookup_elem(&task_states, &key);
672 bpf_map_update_elem(&task_states, &key, &state, BPF_ANY);
678 __u64 now = bpf_ktime_get_ns();
682 token = bpf_map_lookup_elem(&auth_tokens, &tgid);
685 bpf_map_delete_elem(&auth_tokens, &tgid);
690 token = bpf_map_lookup_elem(&auth_tokens, &ppid);
693 bpf_map_delete_elem(&auth_tokens, &ppid);
702 const struct rg_file_key *file_key,
bool have_file_key,
bool authorized,
703 __u32 *reason_flags, __u32 *rule_id)
716 if (!have_file_key) {
719 rule = bpf_map_lookup_elem(&denied_execs, file_key);
729 rule = bpf_map_lookup_elem(&trusted_execs, file_key);
748 bool protected_audit_only,
755 if (protected_change && !protected_audit_only &&
764 __u32 type, __u32 verdict, __u32 reason_flags, __u32 rule_id,
765 __u32 old_euid, __u32 new_euid, __s32 flags, __u32 auxiliary,
766 const struct rg_file_key *file_key,
const char *kernel_filename,
767 const char *kernel_xattr, __u32 old_mode, __u32 new_mode,
768 __u32 old_uid, __u32 new_uid, __u32 old_gid, __u32 new_gid)
779 event = bpf_ringbuf_reserve(&events,
sizeof(*event), 0);
783 __builtin_memset(event, 0,
sizeof(*event));
784 event->timestamp_ns = bpf_ktime_get_ns();
788 event->event_type = type;
792 event->lsm_flags = flags;
801 event->file = *file_key;
802 bpf_get_current_comm(event->
comm,
sizeof(event->
comm));
808 bpf_probe_read_kernel_str(event->
filename,
818 bpf_ringbuf_submit(event, 0);
827 if (bpf_probe_read_kernel_str(value,
sizeof(value), name) <= 0)
830 if (__builtin_memcmp(value,
"security.capability", 20) == 0)
832 if (__builtin_memcmp(value,
"security.ima", 13) == 0 ||
833 __builtin_memcmp(value,
"security.evm", 13) == 0)
835 if (__builtin_memcmp(value,
"security.selinux", 17) == 0 ||
836 __builtin_memcmp(value,
"security.apparmor", 18) == 0)
842 __u32 *mode, __u32 *uid, __u32 *gid)
844 kuid_t inode_uid = {};
845 kgid_t inode_gid = {};
847 *mode = BPF_CORE_READ(inode, i_mode) & 07777U;
848 BPF_CORE_READ_INTO(&inode_uid, inode, i_uid);
849 BPF_CORE_READ_INTO(&inode_gid, inode, i_gid);
850 *uid = inode_uid.val;
851 *gid = inode_gid.val;
856int
BPF_PROG(rg_task_alloc, struct task_struct *task,
857 unsigned long clone_flags,
int ret)
859 struct task_struct *current;
860 const struct cred *cred;
863 __u64 parent_key, child_key;
874 current = (
struct task_struct *)bpf_get_current_task_btf();
877 parent_state = bpf_map_lookup_elem(&task_states, &parent_key);
879 state = *parent_state;
881 cred = BPF_CORE_READ(current, cred);
886 bpf_map_update_elem(&task_states, &child_key, &state, BPF_ANY);
891SEC(
"lsm/task_fix_setuid")
892int
BPF_PROG(rg_task_fix_setuid, struct cred *new, const struct cred *old,
896 __u32 old_euid, new_euid, pid, tgid, ppid;
897 __u32 reason_flags, rule_id, verdict;
898 bool authorized, have_file_key;
910 struct task_struct *task =
911 (
struct task_struct *)bpf_get_current_task_btf();
922 &reason_flags, &rule_id);
928 old_euid, new_euid, flags, 0,
929 have_file_key ? &file_key : 0, 0, 0,
936SEC(
"lsm/bprm_check_security")
937int
BPF_PROG(rg_bprm_check_security, struct linux_binprm *bprm,
int ret)
939 struct task_struct *task;
940 const struct cred *old_cred;
941 const struct cred *new_cred;
942 const struct file *file;
943 const char *filename;
945 __u32 old_euid, new_euid, pid, tgid, ppid;
946 __u32 reason_flags, rule_id, verdict;
947 bool authorized, have_file_key;
953 task = (
struct task_struct *)bpf_get_current_task_btf();
954 old_cred = BPF_CORE_READ(task, cred);
956 new_cred = BPF_CORE_READ(bprm, cred);
964 file = BPF_CORE_READ(bprm, file);
978 &reason_flags, &rule_id);
979 filename = BPF_CORE_READ(bprm, filename);
985 old_euid, new_euid, 0, 0,
986 have_file_key ? &file_key : 0, filename, 0,
999 __u32 auxiliary, __s32 operation_flags,
1002 struct task_struct *task;
1003 const struct cred *cred;
1007 __u32 uid, euid, verdict;
1009 task = (
struct task_struct *)bpf_get_current_task_btf();
1010 cred = BPF_CORE_READ(task, cred);
1020 state = bpf_map_lookup_elem(&task_states, &key);
1035 trusted_rule = bpf_map_lookup_elem(&trusted_execs,
1056 auxiliary, file_key, 0, 0,
1057 0, 0, uid, uid, 0, 0);
1064int
BPF_PROG(rg_capable, const struct cred *cred, struct user_namespace *ns,
1065 int cap,
unsigned int opts,
int ret)
1067 const struct cred *current_cred;
1074 if (cred != current_cred)
1085SEC(
"lsm/inode_permission")
1086int
BPF_PROG(rg_inode_permission, struct inode *inode,
int mask,
int ret)
1097 have_key ? &key : 0);
1113 have_key ? &key : 0);
1116SEC(
"lsm/path_chmod")
1117int
BPF_PROG(rg_path_chmod, const struct path *path, umode_t mode,
int ret)
1125SEC(
"lsm/path_chown")
1127 const struct path *, path,
1147SEC(
"lsm/inode_setattr")
1149 struct dentry *dentry, struct iattr *attr,
int ret)
1154 struct inode *inode;
1155 __u32 old_mode, new_mode, old_uid, new_uid, old_gid, new_gid;
1156 __u32 valid, reasons = 0, protected_reasons = 0, global_reasons = 0;
1157 __u32 verdict, event_type, metadata_decision = 0, burst_count = 0;
1169 inode = BPF_CORE_READ(dentry, d_inode);
1171 valid = BPF_CORE_READ(attr, ia_valid);
1172 new_mode = old_mode;
1177 new_mode = BPF_CORE_READ(attr, ia_mode) & 07777U;
1180 BPF_CORE_READ_INTO(&uid, attr, ia_uid);
1185 BPF_CORE_READ_INTO(&gid, attr, ia_gid);
1196 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1200 new_mode != protected->baseline_mode)
1204 (new_uid != protected->baseline_uid ||
1205 new_gid != protected->baseline_gid))
1232 if ((valid &
ATTR_UID) && old_uid != 0 && new_uid == 0)
1239 if ((valid &
ATTR_MODE) && old_uid == 0 && new_uid == 0 &&
1246 if (!
protected && cfg &&
1248 bool burst_candidate =
false;
1261 burst_candidate =
true;
1262 if ((valid &
ATTR_UID) && old_uid != 0 && new_uid == 0)
1263 burst_candidate =
true;
1266 burst_candidate, global_reasons != 0, &burst_count);
1269 if (global_reasons &&
1274 reasons |= global_reasons | protected_reasons;
1279 protected_reasons != 0,
1282 event_type = (((valid &
ATTR_UID) && new_uid != old_uid) ||
1283 ((valid &
ATTR_GID) && new_gid != old_gid))
1290 protected ? protected->rule_id : 0,
1291 actor_euid, actor_euid,
1293 old_mode, new_mode, old_uid, new_uid, old_gid, new_gid);
1301 int operation_flags)
1306 struct inode *inode;
1307 __u32 current_mode = 0, current_uid = 0, current_gid = 0;
1308 __u32 reasons = 0, protected_reasons = 0, verdict, metadata_decision = 0;
1317 inode = BPF_CORE_READ(dentry, d_inode);
1318 inode_metadata(inode, ¤t_mode, ¤t_uid, ¤t_gid);
1324 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1329 else if (kind == 2 &&
1332 else if (kind == 3 &&
1338 if (!
protected && kind == 1 && operation_flags >= 0 && cfg &&
1345 reasons |= protected_reasons;
1350 protected_reasons != 0,
1354 protected ? protected->rule_id : 0,
1355 0, 0, operation_flags, (__u32)kind,
1357 current_mode, current_mode,
1358 current_uid, current_uid, current_gid, current_gid);
1362SEC(
"lsm/inode_setxattr")
1363int
BPF_PROG(rg_inode_setxattr, struct mnt_idmap *idmap,
1364 struct dentry *dentry, const
char *name, const
void *value,
1365 size_t size,
int flags,
int ret)
1373SEC(
"lsm/inode_removexattr")
1374int
BPF_PROG(rg_inode_removexattr, struct mnt_idmap *idmap,
1375 struct dentry *dentry, const
char *name,
int ret)
1383SEC(
"lsm/inode_set_acl")
1385 struct dentry *dentry, const
char *acl_name,
1386 struct posix_acl *kacl,
int ret)
1401 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1406 protected->rule_id, 0, 0, 1, 0,
1420SEC(
"lsm/inode_remove_acl")
1421int
BPF_PROG(rg_inode_remove_acl, struct mnt_idmap *idmap,
1422 struct dentry *dentry, const
char *acl_name,
int ret)
1437 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1442 protected->rule_id, 0, 0, -1, 0,
1452SEC(
"lsm/inode_unlink")
1454 struct dentry *dentry,
int ret)
1469 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1482SEC(
"lsm/inode_rename")
1484 struct dentry *old_dentry, struct inode *new_dir,
1485 struct dentry *new_dentry,
int ret)
1500 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1502 protected = bpf_map_lookup_elem(&protected_inodes, &key);
1515SEC(
"tp/sched/sched_process_exit")
1518 __u64 ids = bpf_get_current_pid_tgid();
1519 __u32 pid = (__u32)ids;
1520 __u32 tgid = (__u32)(ids >> 32);
1523 bpf_map_delete_elem(&exec_contexts, &tgid);
1524 bpf_map_delete_elem(&pending_paths, &ids);
1528SEC(
"lsm/inode_link")
1530 struct inode *dir, struct dentry *new_dentry,
int ret)
1545 protected = bpf_map_lookup_elem(&protected_inodes, &key);
static __always_inline int xattr_kind(const char *name)
static __always_inline bool file_key_from_file(const struct file *file, struct rg_file_key *key)
static __always_inline bool runtime_path_is_run(const char *path)
static __always_inline bool consume_pending_path(const struct rg_file_key *file_key, char *destination, __u32 *path_resolution)
int BPF_PROG(rg_task_alloc, struct task_struct *task, unsigned long clone_flags, int ret)
#define RG_METADATA_DECISION_BURST
static __always_inline bool file_key_from_inode(const struct inode *inode, struct rg_file_key *key)
static __always_inline void emit_event(__u32 type, __u32 verdict, __u32 reason_flags, __u32 rule_id, __u32 old_euid, __u32 new_euid, __s32 flags, __u32 auxiliary, const struct rg_file_key *file_key, const char *kernel_filename, const char *kernel_xattr, __u32 old_mode, __u32 new_mode, __u32 old_uid, __u32 new_uid, __u32 old_gid, __u32 new_gid)
static __always_inline __u32 cred_uid(const struct cred *cred)
static __always_inline int handle_xattr_change(struct dentry *dentry, const char *name, int operation_flags)
static __always_inline void inode_metadata(const struct inode *inode, __u32 *mode, __u32 *uid, __u32 *gid)
static __always_inline bool pending_path_is_under_run(const struct rg_file_key *file_key)
static __always_inline bool parent_executable_key(struct rg_file_key *key)
static __always_inline bool file_key_equal(const struct rg_file_key *left, const struct rg_file_key *right)
static __always_inline const struct rg_kernel_config * kernel_config(void)
static __always_inline __u64 task_key(const struct task_struct *task)
static __always_inline void record_pending_path(const struct path *path, __u32 operation)
static __always_inline __u32 decide_escalation(const struct rg_file_key *file_key, bool have_file_key, bool authorized, __u32 *reason_flags, __u32 *rule_id)
static __always_inline bool current_executable_key(struct rg_file_key *key)
static __always_inline const struct cred * current_cred_ptr(void)
static __always_inline void mark_current_authorized_root(void)
static __always_inline int guard_current_root_provenance(__u32 auxiliary, __s32 operation_flags, const struct rg_file_key *file_key)
static __always_inline __u32 metadata_verdict(bool protected_change, bool protected_audit_only, bool global_change)
static __always_inline int lsm_result_from_verdict(__u32 verdict)
static __always_inline void observe_task(struct task_struct *task, __u32 uid, __u32 euid)
static __always_inline void enrich_event_actor(struct rg_event *event)
__uint(type, BPF_MAP_TYPE_RINGBUF)
static __always_inline __u32 observe_unprotected_metadata(bool count_burst_candidate, bool request_sample, __u32 *burst_count)
static __always_inline void observe_current_task(const struct cred *cred)
#define RG_METADATA_DECISION_SAMPLE
static __always_inline void current_ids(__u32 *pid, __u32 *tgid, __u32 *ppid)
int BPF_PROG2(rg_path_chown, const struct path *, path, kuid_t, uid, kgid_t, gid, int, ret)
int bpf_path_d_path(const struct path *path, char *buf, size_t buf__sz) __weak __ksym
static __always_inline __u32 current_euid_value(void)
int rg_sched_process_exit(struct trace_event_raw_sched_process_template *ctx)
static __always_inline bool consume_token_for(__u32 tgid, __u32 ppid, __u32 target_euid)
static __always_inline void capture_exec_context(struct linux_binprm *bprm, const struct rg_file_key *key)
static __always_inline void copy_map_string(char *destination, const char *source, __u32 size)
static __always_inline __u32 cred_euid(const struct cred *cred)
static __always_inline void discard_pending_path(void)
static __always_inline const char * dentry_name_ptr(const struct dentry *dentry)
static __always_inline bool file_key_from_dentry(const struct dentry *dentry, struct rg_file_key *key)
@ RG_REASON_PROTECTED_OWNER
@ RG_REASON_PROTECTED_UNLINK
@ RG_REASON_SECURITY_LABEL
@ RG_REASON_PROTECTED_ACL
@ RG_REASON_SECURITY_CAPABILITY
@ RG_REASON_ROOT_OWNED_WRITE_EXPOSURE
@ RG_REASON_FILE_ID_UNAVAILABLE
@ RG_REASON_DIRECT_CRED_ANOMALY
@ RG_REASON_METADATA_BURST
@ RG_REASON_INTEGRITY_XATTR
@ RG_REASON_OWNER_TO_ROOT
@ RG_REASON_PROTECTED_HARDLINK
@ RG_REASON_GLOBAL_METADATA
@ RG_REASON_PROTECTED_MODE
@ RG_REASON_PROTECTED_RENAME
#define RG_XATTR_NAME_LEN
@ RG_EVENT_PROTECTED_RENAME
@ RG_EVENT_PROTECTED_UNLINK
@ RG_EVENT_PROTECTED_HARDLINK
@ RG_EVENT_CREDENTIAL_ANOMALY
@ RG_EVENT_PERMISSION_CHANGE
@ RG_PROTECT_INTEGRITY_XATTR
@ RG_PROTECT_CAPABILITY_XATTR
@ RG_PROTECT_SECURITY_LABEL
struct rg_file_key actor_file
char filename[RG_FILENAME_LEN]
char xattr_name[RG_XATTR_NAME_LEN]
char parent_executable[RG_FILENAME_LEN]
char actor_executable[RG_FILENAME_LEN]
__u64 actor_start_boottime_ns
char parent_comm[RG_COMM_LEN]
struct rg_file_key executable
char executable_path[RG_FILENAME_LEN]
__u32 global_metadata_sample_limit
__u32 metadata_burst_cooldown_ms
__u32 metadata_burst_window_ms
__u32 monitor_global_privilege_metadata
__u32 ignore_run_global_metadata
__u32 detect_global_metadata_bursts
__u32 global_metadata_action
__u32 metadata_burst_threshold
struct rg_file_key parent
struct bpf_spin_lock lock
char path[RG_FILENAME_LEN]