From 794a305118110157d9d17a637347ad5869766463 Mon Sep 17 00:00:00 2001 From: yuelg Date: Thu, 7 Nov 2024 08:23:49 +0000 Subject: [PATCH] extract common function Signed-off-by: yuelg --- pkg/audit/fileaccess/audit.go | 2 +- pkg/bpf/c/common_structs.h | 152 +++++++++++++++++++++++++++++++ pkg/bpf/c/restricted-file.bpf.c | 140 ---------------------------- pkg/bpf/c/restricted-mount.bpf.c | 81 +++------------- 4 files changed, 165 insertions(+), 210 deletions(-) diff --git a/pkg/audit/fileaccess/audit.go b/pkg/audit/fileaccess/audit.go index fa57d38..2698a10 100644 --- a/pkg/audit/fileaccess/audit.go +++ b/pkg/audit/fileaccess/audit.go @@ -31,7 +31,7 @@ const ( ) type auditLog struct { - //CGroupID uint64 + CGroupID uint64 PID uint32 UID uint32 Ret int32 diff --git a/pkg/bpf/c/common_structs.h b/pkg/bpf/c/common_structs.h index 9c96fda..592ff60 100644 --- a/pkg/bpf/c/common_structs.h +++ b/pkg/bpf/c/common_structs.h @@ -7,6 +7,16 @@ #define AUDIT_EVENTS_RING_SIZE (4 * 4096) #define TASK_COMM_LEN 16 #define NEW_UTS_LEN 64 +#define NAME_MAX 255 +#define LOOP_NAME 80 +#define MAX_PATH_SIZE 4096 // PATH_MAX from +#define LIMIT_PATH_SIZE(x) ((x) & (MAX_PATH_SIZE - 1)) +#define MAX_PATH_COMPONENTS 20 + +#define MAX_PERCPU_ARRAY_SIZE (1 << 15) +#define HALF_PERCPU_ARRAY_SIZE (MAX_PERCPU_ARRAY_SIZE >> 1) +#define LIMIT_PERCPU_ARRAY_SIZE(x) ((x) & (MAX_PERCPU_ARRAY_SIZE - 1)) +#define LIMIT_HALF_PERCPU_ARRAY_SIZE(x) ((x) & (HALF_PERCPU_ARRAY_SIZE - 1)) #define VERSION_5_10 KERNEL_VERSION(5,10,0) #define NULL ((void *)0) @@ -45,6 +55,51 @@ enum lsm_hook_point SENDMSG // Not implemented yet. }; +struct file_path { + unsigned char path[NAME_MAX]; +}; + +struct callback_ctx { + unsigned char *path; + bool found; +}; + +struct file_open_audit_event { + u64 cgroup; + u32 pid; + u32 uid; + int ret; + char nodename[NEW_UTS_LEN + 1]; + char task[TASK_COMM_LEN]; + char parent_task[TASK_COMM_LEN]; + unsigned char path[NAME_MAX]; +}; //512 stack size restrict, now [479 - 64(cgroup) + 32(uid)] + other_stack + +struct fileopen_safeguard_config { + u32 mode; + u32 target; +}; + +struct mount_audit_event { + u64 cgroup; + u32 pid; + u32 uid; + int ret; + char nodename[NEW_UTS_LEN + 1]; + char task[TASK_COMM_LEN]; + char parent_task[TASK_COMM_LEN]; + unsigned char path[NAME_MAX]; +}; + +struct mount_safeguard_config { + u32 mode; + u32 target; +}; + +struct buffer { + u8 data[MAX_PERCPU_ARRAY_SIZE]; +}; + static inline int _is_host_mntns() { struct task_struct *current_task; @@ -98,3 +153,100 @@ static __always_inline int strlen(const unsigned char *s, size_t max_len) return i; } + +static long get_path_str_from_path(u_char **path_str, const struct path *path, struct buffer *out_buf, struct dentry *append) { + long ret; + struct dentry *dentry, *dentry_parent, *dentry_mnt; + struct vfsmount *vfsmnt; + struct mount *mnt, *mnt_parent; + const u_char *name; + size_t name_len; + + dentry = BPF_CORE_READ(path, dentry); + vfsmnt = BPF_CORE_READ(path, mnt); + mnt = container_of(vfsmnt, struct mount, mnt); + mnt_parent = BPF_CORE_READ(mnt, mnt_parent); + + size_t buf_off = HALF_PERCPU_ARRAY_SIZE - 1; + +#pragma unroll + for (int i = 0; i < MAX_PATH_COMPONENTS; i++) { + + dentry_mnt = BPF_CORE_READ(vfsmnt, mnt_root); + dentry_parent = BPF_CORE_READ(dentry, d_parent); + + if (dentry == dentry_mnt || dentry == dentry_parent) { + if (dentry != dentry_mnt) { + // We reached root, but not mount root - escaped? + break; + } + if (mnt != mnt_parent) { + // We reached root, but not global root - continue with mount point path + dentry = BPF_CORE_READ(mnt, mnt_mountpoint); + mnt_parent = BPF_CORE_READ(mnt, mnt_parent); + vfsmnt = __builtin_preserve_access_index(&mnt->mnt); + continue; + } + // Global root - path fully parsed + break; + } + + // Add this dentry name to path + name_len = LIMIT_PATH_SIZE(BPF_CORE_READ(dentry, d_name.len)); + name = BPF_CORE_READ(dentry, d_name.name); + + name_len = name_len + 1; + // Is string buffer big enough for dentry name? + if (name_len > buf_off) { break; } + volatile size_t new_buff_offset = buf_off - name_len; // satisfy verifier + ret = bpf_probe_read_kernel_str( + &(out_buf->data[LIMIT_HALF_PERCPU_ARRAY_SIZE(new_buff_offset)]),// satisfy verifie + name_len, name); + + if (ret < 0) { return ret; } + + if (ret > 1) { + buf_off -= 1; // remove null byte termination with slash sign + buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier + out_buf->data[buf_off] = '/'; + buf_off -= ret - 1; + buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier + } else { + // If sz is 0 or 1 we have an error (path can't be null nor an empty string) + break; + } + dentry = dentry_parent; + } + + // Is string buffer big enough for slash? + if (buf_off != 0) { + // Add leading slash + buf_off -= 1; + buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier + out_buf->data[buf_off] = '/'; + } + + // Null terminate the path string + out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1] = 0; + *path_str = &out_buf->data[buf_off]; + + if (append) { + name_len = LIMIT_PATH_SIZE(BPF_CORE_READ(append, d_name.len)); + name = BPF_CORE_READ(append, d_name.name); + + ret = bpf_probe_read_kernel_str(&(out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1]), name_len + 1, name); + } else { + out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1 - 1] = 0; + } + + return HALF_PERCPU_ARRAY_SIZE - buf_off - 1; +} + +static u64 cb_check_path(struct bpf_map *map, u32 *key, struct file_path *map_path, struct callback_ctx *ctx) { + size_t size = strlen(map_path->path, NAME_MAX); + if (strcmp(map_path->path, ctx->path, size) == 0) { + ctx->found = true; + } + + return 0; +} diff --git a/pkg/bpf/c/restricted-file.bpf.c b/pkg/bpf/c/restricted-file.bpf.c index bfe20fc..b2ece84 100644 --- a/pkg/bpf/c/restricted-file.bpf.c +++ b/pkg/bpf/c/restricted-file.bpf.c @@ -8,34 +8,6 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -#define NAME_MAX 255 -#define LOOP_NAME 80 - -struct file_path { - unsigned char path[NAME_MAX]; -}; - -struct callback_ctx { - unsigned char *path; - bool found; -}; - -struct file_open_audit_event { - u64 cgroup; - u32 pid; - u32 uid; - int ret; - char nodename[NEW_UTS_LEN + 1]; - char task[TASK_COMM_LEN]; - char parent_task[TASK_COMM_LEN]; - unsigned char path[NAME_MAX]; -}; //512 stack size restrict, now [479 - 64(cgroup) + 32(uid)] + other_stack - -struct fileopen_safeguard_config { - u32 mode; - u32 target; -}; - struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(u32)); @@ -46,21 +18,6 @@ BPF_HASH(fileopen_safeguard_config_map, u32, struct fileopen_safeguard_config, 2 BPF_HASH(allowed_access_files, u32, struct file_path, 256); BPF_HASH(denied_access_files, u32, struct file_path, 256); - - -#define MAX_PATH_SIZE 4096 // PATH_MAX from -#define LIMIT_PATH_SIZE(x) ((x) & (MAX_PATH_SIZE - 1)) -#define MAX_PATH_COMPONENTS 20 - -#define MAX_PERCPU_ARRAY_SIZE (1 << 15) -#define HALF_PERCPU_ARRAY_SIZE (MAX_PERCPU_ARRAY_SIZE >> 1) -#define LIMIT_PERCPU_ARRAY_SIZE(x) ((x) & (MAX_PERCPU_ARRAY_SIZE - 1)) -#define LIMIT_HALF_PERCPU_ARRAY_SIZE(x) ((x) & (HALF_PERCPU_ARRAY_SIZE - 1)) - -struct buffer { - u8 data[MAX_PERCPU_ARRAY_SIZE]; -}; - struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __type(key, u32); @@ -73,103 +30,6 @@ static struct buffer *get_buffer() { return (struct buffer *)bpf_map_lookup_elem(&heaps_map, &zero); } -static long get_path_str_from_path(u_char **path_str, const struct path *path, struct buffer *out_buf, struct dentry *append) { - long ret; - struct dentry *dentry, *dentry_parent, *dentry_mnt; - struct vfsmount *vfsmnt; - struct mount *mnt, *mnt_parent; - const u_char *name; - size_t name_len; - - dentry = BPF_CORE_READ(path, dentry); - vfsmnt = BPF_CORE_READ(path, mnt); - mnt = container_of(vfsmnt, struct mount, mnt); - mnt_parent = BPF_CORE_READ(mnt, mnt_parent); - - size_t buf_off = HALF_PERCPU_ARRAY_SIZE - 1; - -#pragma unroll - for (int i = 0; i < MAX_PATH_COMPONENTS; i++) { - - dentry_mnt = BPF_CORE_READ(vfsmnt, mnt_root); - dentry_parent = BPF_CORE_READ(dentry, d_parent); - - if (dentry == dentry_mnt || dentry == dentry_parent) { - if (dentry != dentry_mnt) { - // We reached root, but not mount root - escaped? - break; - } - if (mnt != mnt_parent) { - // We reached root, but not global root - continue with mount point path - dentry = BPF_CORE_READ(mnt, mnt_mountpoint); - mnt_parent = BPF_CORE_READ(mnt, mnt_parent); - vfsmnt = __builtin_preserve_access_index(&mnt->mnt); - continue; - } - // Global root - path fully parsed - break; - } - - // Add this dentry name to path - name_len = LIMIT_PATH_SIZE(BPF_CORE_READ(dentry, d_name.len)); - name = BPF_CORE_READ(dentry, d_name.name); - - name_len = name_len + 1; - // Is string buffer big enough for dentry name? - if (name_len > buf_off) { break; } - volatile size_t new_buff_offset = buf_off - name_len; // satisfy verifier - ret = bpf_probe_read_kernel_str( - &(out_buf->data[LIMIT_HALF_PERCPU_ARRAY_SIZE(new_buff_offset)]),// satisfy verifie - name_len, name); - - if (ret < 0) { return ret; } - - if (ret > 1) { - buf_off -= 1; // remove null byte termination with slash sign - buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier - out_buf->data[buf_off] = '/'; - buf_off -= ret - 1; - buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier - } else { - // If sz is 0 or 1 we have an error (path can't be null nor an empty string) - break; - } - dentry = dentry_parent; - } - - // Is string buffer big enough for slash? - if (buf_off != 0) { - // Add leading slash - buf_off -= 1; - buf_off = LIMIT_HALF_PERCPU_ARRAY_SIZE(buf_off); // satisfy verifier - out_buf->data[buf_off] = '/'; - } - - // Null terminate the path string - out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1] = 0; - *path_str = &out_buf->data[buf_off]; - - if (append) { - name_len = LIMIT_PATH_SIZE(BPF_CORE_READ(append, d_name.len)); - name = BPF_CORE_READ(append, d_name.name); - - ret = bpf_probe_read_kernel_str(&(out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1]), name_len + 1, name); - } else { - out_buf->data[HALF_PERCPU_ARRAY_SIZE - 1 - 1] = 0; - } - - return HALF_PERCPU_ARRAY_SIZE - buf_off - 1; -} - -static u64 cb_check_path(struct bpf_map *map, u32 *key, struct file_path *map_path, struct callback_ctx *ctx) { - size_t size = strlen(map_path->path, NAME_MAX); - if (strcmp(map_path->path, ctx->path, size) == 0) { - ctx->found = true; - } - - return 0; -} - static inline void get_file_info(struct file_open_audit_event *event){ struct task_struct *current_task; struct uts_namespace *uts_ns; diff --git a/pkg/bpf/c/restricted-mount.bpf.c b/pkg/bpf/c/restricted-mount.bpf.c index 46ca578..1c0c090 100644 --- a/pkg/bpf/c/restricted-mount.bpf.c +++ b/pkg/bpf/c/restricted-mount.bpf.c @@ -8,34 +8,6 @@ char LICENSE[] SEC("license") = "Dual BSD/GPL"; -#define NAME_MAX 255 -#define LOOP_NAME 70 - -struct file_path { - unsigned char path[NAME_MAX]; -}; - -struct callback_ctx { - unsigned char *path; - bool found; -}; - -struct mount_audit_event { - u64 cgroup; - u32 pid; - u32 uid; - int ret; - char nodename[NEW_UTS_LEN + 1]; - char task[TASK_COMM_LEN]; - char parent_task[TASK_COMM_LEN]; - unsigned char path[NAME_MAX]; -}; - -struct mount_safeguard_config { - u32 mode; - u32 target; -}; - struct { __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); __uint(key_size, sizeof(u32)); @@ -45,31 +17,17 @@ struct { BPF_HASH(mount_safeguard_config_map, u32, struct mount_safeguard_config, 256); BPF_HASH(mount_denied_source_list, u32, struct file_path, 256); -static u64 cb_check_path(struct bpf_map *map, u32 *key, struct file_path *map_path, struct callback_ctx *ctx) -{ - size_t size = strlen(map_path->path, NAME_MAX); - if (strcmp(map_path->path, ctx->path, size) == 0) { - ctx->found = 1; - } - - return 0; -} - +/* static inline void get_info(struct mount_audit_event *event, const char *dev_name) { unsigned int inum; - struct task_struct *current_task, *parent_task; struct uts_namespace *uts_ns; struct mnt_namespace *mnt_ns; struct nsproxy *nsproxy; - current_task = (struct task_struct *)bpf_get_current_task(); - parent_task = BPF_CORE_READ(current_task, real_parent); - - BPF_CORE_READ_INTO(&nsproxy, current_task, nsproxy); - BPF_CORE_READ_INTO(&uts_ns, nsproxy, uts_ns); - BPF_CORE_READ_INTO(&event->nodename, uts_ns, name.nodename); - BPF_CORE_READ_INTO(&mnt_ns, nsproxy, mnt_ns); - BPF_CORE_READ_INTO(&inum, mnt_ns, ns.inum); + struct task_struct *current_task = (struct task_struct *)bpf_get_current_task(); + struct task_struct *parent_task = BPF_CORE_READ(current_task, real_parent); + BPF_CORE_READ_INTO(&event.nodename, current_task, nsproxy, uts_ns, name.nodename); + BPF_CORE_READ_INTO(&inum, current_task, nsproxy, mnt_ns, ns.inum); event->cgroup = bpf_get_current_cgroup_id(); event->pid = (u32)(bpf_get_current_pid_tgid() >> 32); @@ -81,7 +39,6 @@ static inline void get_info(struct mount_audit_event *event, const char *dev_nam event->uid = uid_gid & 0xFFFFFFFF; } -/* static inline int get_perm(struct mount_audit_event *event){ volatile int ret = 0; volatile bool find = false; @@ -160,27 +117,22 @@ int BPF_PROG(restricted_mount, const char *dev_name, const struct path *path) { SEC("lsm/sb_mount") int BPF_PROG(restricted_mount, const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data, int ret_prev) + const char *type, unsigned long flags, void *data) { - int ret = -1; + int ret = 0; int index = 0; unsigned int inum; bool find = false; - struct task_struct *current_task; struct mount_audit_event event = {}; struct uts_namespace *uts_ns; struct mnt_namespace *mnt_ns; struct nsproxy *nsproxy; struct mount_safeguard_config *config = (struct mount_safeguard_config *)bpf_map_lookup_elem(&mount_safeguard_config_map, &index); - current_task = (struct task_struct *)bpf_get_current_task(); + struct task_struct *current_task = (struct task_struct *)bpf_get_current_task(); struct task_struct *parent_task = BPF_CORE_READ(current_task, real_parent); - - BPF_CORE_READ_INTO(&nsproxy, current_task, nsproxy); - BPF_CORE_READ_INTO(&uts_ns, nsproxy, uts_ns); - BPF_CORE_READ_INTO(&event.nodename, uts_ns, name.nodename); - BPF_CORE_READ_INTO(&mnt_ns, nsproxy, mnt_ns); - BPF_CORE_READ_INTO(&inum, mnt_ns, ns.inum); + BPF_CORE_READ_INTO(&event.nodename, current_task, nsproxy, uts_ns, name.nodename); + BPF_CORE_READ_INTO(&inum, current_task, nsproxy, mnt_ns, ns.inum); event.cgroup = bpf_get_current_cgroup_id(); event.pid = (u32)(bpf_get_current_pid_tgid() >> 32); @@ -272,15 +224,8 @@ int BPF_PROG(restricted_move_mount, const struct path *from_path, const struct p struct task_struct *current_task = (struct task_struct *)bpf_get_current_task(); struct task_struct *parent_task = BPF_CORE_READ(current_task, real_parent); - /* - BPF_CORE_READ_INTO(&nsproxy, current_task, nsproxy); - BPF_CORE_READ_INTO(&uts_ns, nsproxy, uts_ns); - BPF_CORE_READ_INTO(&event.nodename, uts_ns, name.nodename); - BPF_CORE_READ_INTO(&mnt_ns, nsproxy, mnt_ns); - BPF_CORE_READ_INTO(&inum, mnt_ns, ns.inum); - */ - BPF_CORE_READ_INTO(&event.nodename, current_task, nsproxy, uts_ns, name.nodename); - BPF_CORE_READ_INTO(&inum, current_task, nsproxy, mnt_ns, ns.inum); + BPF_CORE_READ_INTO(&event.nodename, current_task, nsproxy, uts_ns, name.nodename); + BPF_CORE_READ_INTO(&inum, current_task, nsproxy, mnt_ns, ns.inum); event.cgroup = bpf_get_current_cgroup_id(); event.pid = (u32)(bpf_get_current_pid_tgid() >> 32); @@ -290,8 +235,6 @@ int BPF_PROG(restricted_move_mount, const struct path *from_path, const struct p #if LINUX_VERSION_CODE > VERSION_5_10 name = BPF_CORE_READ(old, mnt_devname); bpf_probe_read_kernel_str(&event.path, sizeof(event.path), name); - //bpf_printk("from_path %s\n", event.path); - //bpf_printk("to_path %s\n", BPF_CORE_READ(p, mnt_devname)); struct callback_ctx cb = { .path = event.path, .found = false }; bpf_for_each_map_elem(&mount_denied_source_list, cb_check_path, &cb, 0); -- Gitee