diff --git a/KubeArmor/BPF/enforcer.bpf.c b/KubeArmor/BPF/enforcer.bpf.c index 811c25d546..65e22725a9 100644 --- a/KubeArmor/BPF/enforcer.bpf.c +++ b/KubeArmor/BPF/enforcer.bpf.c @@ -9,6 +9,7 @@ SEC("lsm/bprm_check_security") int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) { struct task_struct *t = (struct task_struct *)bpf_get_current_task(); event *task_info; + int retval = ret; bool match = false; @@ -108,20 +109,20 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) { if ((dirval->processmask & RULE_RECURSIVE) && (~dirval->processmask & RULE_HINT)) { // true directory match and not a hint suggests - // there are no possibility of child dir + // there are no possibility of child dir val = dirval; goto decision; } else if (dirval->processmask & RULE_RECURSIVE) { // It's a directory match but also a - // hint, it's possible that a - // subdirectory exists that can also - // match so we continue the loop to look - // for a true match in subdirectories + // hint, it's possible that a + // subdirectory exists that can also + // match so we continue the loop to look + // for a true match in subdirectories recursivebuthint = true; val = dirval; } else { continue; // We continue the loop to see if we have more nested - // directories and set match to false + // directories and set match to false } } } else { @@ -203,65 +204,64 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) { } decision: - task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); - if (!task_info) { - return 0; - } - - // Clearing arrays to avoid garbage values - __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); - __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); - - init_context(task_info); - bpf_probe_read_str(&task_info->data.path, MAX_STRING_SIZE, store->path); - bpf_probe_read_str(&task_info->data.source, MAX_STRING_SIZE, - store->source); task_info->event_id = _SECURITY_BPRM_CHECK; - task_info->retval = -EPERM; if (match) { if (val && (val->processmask & RULE_OWNER)) { if (!is_owner(bprm->file)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; } else { - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); + // Owner Only Rule Match, No need to enforce return ret; } } if (val && (val->processmask & RULE_DENY)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; } } + if (retval == -EPERM) { + goto ringbuf; + } + bpf_map_update_elem(&bufk, &two, z, BPF_ANY); pk->path[0] = dproc; struct data_t *allow = bpf_map_lookup_elem(inner, pk); if (allow) { if (!match) { - if(allow->processmask == BLOCK_POSTURE) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } else { - task_info->retval = ret; - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return ret; - } - } - // Do not remove this else block - else { - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); - return ret; + if (allow->processmask == BLOCK_POSTURE) { + retval = -EPERM; + } + goto ringbuf; } } - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); return ret; + +ringbuf: + + task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); + if (!task_info) { + // Failed to reserve, doing policy enforcement without alert + return retval; + } + + // Clearing arrays to avoid garbage values + __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); + __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); + + init_context(task_info); + bpf_probe_read_str(&task_info->data.path, MAX_STRING_SIZE, store->path); + bpf_probe_read_str(&task_info->data.source, MAX_STRING_SIZE, store->source); + task_info->event_id = _SECURITY_BPRM_CHECK; + task_info->retval = retval; + bpf_ringbuf_submit(task_info, 0); + return retval; } static inline int match_net_rules(int type, int protocol, u32 eventID) { event *task_info; + int retval = 0; struct task_struct *t = (struct task_struct *)bpf_get_current_task(); @@ -319,7 +319,8 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) { if (type == SOCK_STREAM && (protocol == IPPROTO_TCP || protocol == 0)) { p0 = sock_proto; p1 = IPPROTO_TCP; - } else if (type == SOCK_DGRAM && (protocol == IPPROTO_UDP || protocol == 0)) { + } else if (type == SOCK_DGRAM && + (protocol == IPPROTO_UDP || protocol == 0)) { p0 = sock_proto; p1 = IPPROTO_UDP; } else if (protocol == IPPROTO_ICMP && @@ -343,8 +344,8 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) { match = true; goto decision; } - - val = bpf_map_lookup_elem(inner, p); + + val = bpf_map_lookup_elem(inner, p); } bpf_map_update_elem(&bufk, &one, z, BPF_ANY); @@ -360,9 +361,32 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) { decision: + if (match) { + if (val && (val->processmask & RULE_DENY)) { + retval = -EPERM; + goto ringbuf; + } + } + + bpf_map_update_elem(&bufk, &one, z, BPF_ANY); + p->path[0] = dnet; + struct data_t *allow = bpf_map_lookup_elem(inner, p); + + if (allow) { + if (!match) { + if (allow->processmask == BLOCK_POSTURE) { + retval = -EPERM; + } + goto ringbuf; + } + } + + return 0; + +ringbuf: task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); if (!task_info) { - return 0; + return retval; } // Clearing arrays to avoid garbage values to be parsed __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); @@ -374,33 +398,9 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) { task_info->event_id = eventID; - task_info->retval = -EPERM; - - bpf_map_update_elem(&bufk, &one, z, BPF_ANY); - p->path[0] = dnet; - struct data_t *allow = bpf_map_lookup_elem(inner, p); - - if (allow) { - if (!match) { - if(allow->processmask == BLOCK_POSTURE) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } else { - task_info->retval = 0; - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return 0; - } - } - } else { - if (match) { - if (val && (val->processmask & RULE_DENY)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } - } - } - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); - return 0; + task_info->retval = retval; + bpf_ringbuf_submit(task_info, 0); + return retval; } SEC("lsm/socket_create") diff --git a/KubeArmor/BPF/shared.h b/KubeArmor/BPF/shared.h index 7a92c6d3ac..0fe35fb171 100644 --- a/KubeArmor/BPF/shared.h +++ b/KubeArmor/BPF/shared.h @@ -63,7 +63,7 @@ struct { __uint(max_entries, MAX_BUFFERS); } bufs_off SEC(".maps"); -struct { +struct { __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY); __type(key, u32); __type(value, bufs_k); @@ -90,7 +90,7 @@ typedef struct { u32 event_id; s64 retval; - + u8 comm[TASK_COMM_LEN]; bufs_k data; @@ -195,10 +195,10 @@ static __always_inline bool prepend_path(struct path *path, bufs_t *string_p) { int sz = bpf_probe_read_str( &(string_p->buf[(offset) & (MAX_COMBINED_LENGTH - 1)]), (d_name.len + 1) & (MAX_COMBINED_LENGTH - 1), d_name.name); - if (sz > 1) { + if (sz > 1) { bpf_probe_read( - &(string_p->buf[(offset + d_name.len) & (MAX_COMBINED_LENGTH - 1)]), 1, - &slash); + &(string_p->buf[(offset + d_name.len) & (MAX_COMBINED_LENGTH - 1)]), + 1, &slash); } else { offset += (d_name.len + 1); } @@ -213,7 +213,8 @@ static __always_inline bool prepend_path(struct path *path, bufs_t *string_p) { bpf_probe_read(&(string_p->buf[MAX_COMBINED_LENGTH - 1]), 1, &null); offset--; - bpf_probe_read(&(string_p->buf[offset & (MAX_COMBINED_LENGTH - 1)]), 1, &slash); + bpf_probe_read(&(string_p->buf[offset & (MAX_COMBINED_LENGTH - 1)]), 1, + &slash); set_buf_off(PATH_BUFFER, offset); return true; } @@ -287,7 +288,7 @@ static __always_inline u32 init_context(event *event_data) { event_data->uid = bpf_get_current_uid_gid(); -// Clearing array to avoid garbage values + // Clearing array to avoid garbage values __builtin_memset(event_data->comm, 0, sizeof(event_data->comm)); bpf_get_current_comm(&event_data->comm, sizeof(event_data->comm)); @@ -310,11 +311,14 @@ static bool is_owner_path(struct dentry *dent) { return true; } -static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id , u32 eventID) { +static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id, + u32 eventID) { struct task_struct *t = (struct task_struct *)bpf_get_current_task(); event *task_info; + int retval = 0; + bool match = false; struct outer_key okey; @@ -503,95 +507,76 @@ static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id , u32 decision: - task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); - if (!task_info) { - return 0; - } - - init_context(task_info); - // Clearing arrays to avoid garbage values - __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); - __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); - - bpf_probe_read_str(&task_info->data.path, MAX_STRING_SIZE, store->path); - bpf_probe_read_str(&task_info->data.source, MAX_STRING_SIZE, store->source); - - task_info->event_id = eventID; - task_info->retval = -EPERM; - if (id == dpath) { // Path Hooks if (match) { if (val && (val->filemask & RULE_OWNER)) { if (!is_owner_path(f_path->dentry)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; + } else { + return 0; } - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); - return 0; } if (val && (val->filemask & RULE_DENY)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; } } + if (retval == -EPERM) { + goto ringbuf; + } + bpf_map_update_elem(&bufk, &two, z, BPF_ANY); pk->path[0] = dfile; struct data_t *allow = bpf_map_lookup_elem(inner, pk); - if (allow) { + if (allow) { if (!match) { - if(allow->processmask == BLOCK_POSTURE) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } else { - task_info->retval = 0; - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return 0; - } + if (allow->processmask == BLOCK_POSTURE) { + retval = -EPERM; + } + goto ringbuf; } } - + } else if (id == dfileread) { // file open if (match) { if (val && (val->filemask & RULE_OWNER)) { if (!is_owner_path(f_path->dentry)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; + } else { + return 0; } - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); - return 0; } if (val && (val->filemask & RULE_READ) && !(val->filemask & RULE_WRITE)) { - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); // Read Only Policy, Decision making will be done in lsm/file_permission return 0; } if (val && (val->filemask & RULE_DENY)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; } } + if (retval == -EPERM) { + goto ringbuf; + } + bpf_map_update_elem(&bufk, &two, z, BPF_ANY); pk->path[0] = dfile; struct data_t *allow = bpf_map_lookup_elem(inner, pk); - if (allow && !match) { - if(allow->processmask == BLOCK_POSTURE) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } else { - task_info->retval = 0; - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return 0; - } + if (allow) { + if (!match) { + if (allow->processmask == BLOCK_POSTURE) { + retval = -EPERM; + } + goto ringbuf; + } } - } else if (id == dfilewrite) { // fule write + } else if (id == dfilewrite) { // file write if (match) { if (val && (val->filemask & RULE_DENY)) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; + retval = -EPERM; + goto ringbuf; } } @@ -599,21 +584,37 @@ static inline int match_and_enforce_path_hooks(struct path *f_path, u32 id , u32 pk->path[0] = dfile; struct data_t *allow = bpf_map_lookup_elem(inner, pk); - if (allow && !match) { - if(allow->processmask == BLOCK_POSTURE) { - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return -EPERM; - } - else { - task_info->retval= 0; - bpf_ringbuf_submit(task_info, BPF_RB_FORCE_WAKEUP); - return 0; + if (allow) { + if (!match) { + if (allow->processmask == BLOCK_POSTURE) { + retval = -EPERM; } - + goto ringbuf; + } } } - bpf_ringbuf_discard(task_info, BPF_RB_NO_WAKEUP); + return 0; + +ringbuf: + task_info = bpf_ringbuf_reserve(&kubearmor_events, sizeof(event), 0); + if (!task_info) { + // Failed to reserve, doing policy enforcement without alert + return retval; + } + + init_context(task_info); + // Clearing arrays to avoid garbage values + __builtin_memset(task_info->data.path, 0, sizeof(task_info->data.path)); + __builtin_memset(task_info->data.source, 0, sizeof(task_info->data.source)); + + bpf_probe_read_str(&task_info->data.path, MAX_STRING_SIZE, store->path); + bpf_probe_read_str(&task_info->data.source, MAX_STRING_SIZE, store->source); + + task_info->event_id = eventID; + task_info->retval = retval; + bpf_ringbuf_submit(task_info, 0); + return retval; } /* diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o index 6ed17e11bf..ac25760b26 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o and b/KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o index 4da1dbe758..afa58f8714 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o and b/KubeArmor/enforcer/bpflsm/enforcer_bpfel.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o index cf1f1fa115..75d6c3e98f 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o and b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o differ diff --git a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o index 7376c6b49b..a5382e023f 100644 Binary files a/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o and b/KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o differ diff --git a/KubeArmor/utils/bpflsmprobe/probe_bpfeb.o b/KubeArmor/utils/bpflsmprobe/probe_bpfeb.o index 48e797fd5e..0775008831 100644 Binary files a/KubeArmor/utils/bpflsmprobe/probe_bpfeb.o and b/KubeArmor/utils/bpflsmprobe/probe_bpfeb.o differ diff --git a/KubeArmor/utils/bpflsmprobe/probe_bpfel.o b/KubeArmor/utils/bpflsmprobe/probe_bpfel.o index d5d022eccd..4446f3ada9 100644 Binary files a/KubeArmor/utils/bpflsmprobe/probe_bpfel.o and b/KubeArmor/utils/bpflsmprobe/probe_bpfel.o differ