diff --git a/.gitignore b/.gitignore index 25447598696447573cfe102a78696784be1b44d9..97d5b8a291027198be5f74b69cd9bc063d6eb7c2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ Module.symvers modules.order *.mod *.d -*.mod.c \ No newline at end of file +*.mod.c +build/* \ No newline at end of file diff --git a/kerneldriver/core/response_unit/secDetector_response.c b/kerneldriver/core/response_unit/secDetector_response.c index 8a1f07050d92442ed358470221d74fab49a5cbe3..26a3868b610cb259433c38f885ea1b79e5bc2d2b 100644 --- a/kerneldriver/core/response_unit/secDetector_response.c +++ b/kerneldriver/core/response_unit/secDetector_response.c @@ -114,12 +114,12 @@ void free_response_data(uint32_t repsonse_id, response_data_t *rd) } } -int __init secDetector_response_init(void) +int __init secDetector_response_init(unsigned int rb_sz) { - return secDetector_ringbuf_dev_init(); + return secDetector_ringbuf_dev_init(rb_sz); } -void __exit secDetector_response_exit(void) +void secDetector_response_exit(void) { secDetector_ringbuf_dev_exit(); } \ No newline at end of file diff --git a/kerneldriver/core/response_unit/secDetector_ringbuffer.c b/kerneldriver/core/response_unit/secDetector_ringbuffer.c index aab2c72728351ce1fa534ba7d7400b20a59cdc96..b367d74f9de02fd49dea524929a2ac56979ea470 100644 --- a/kerneldriver/core/response_unit/secDetector_ringbuffer.c +++ b/kerneldriver/core/response_unit/secDetector_ringbuffer.c @@ -18,8 +18,9 @@ #include #include -#define rb_datasz (PAGE_SIZE << 10) /* 4Mb */ -#define rb_mask (rb_datasz - 1) +static unsigned long rb_datasz; +static unsigned long rb_mask; + #define MODULE_DEVICE "secDetector" @@ -347,11 +348,14 @@ int secDetector_ringbuf_output(const void *data, u64 size, u64 flags) return ringbuf_output(g_rb, data, size, flags); } -int __init secDetector_ringbuf_dev_init(void) +int __init secDetector_ringbuf_dev_init(unsigned int rb_sz) { struct device *class_dev = NULL; int ret = 0; + rb_datasz = rb_sz; + rb_mask = rb_datasz - 1; + g_rb = ringbuf_alloc(rb_datasz, 0); if (!g_rb) return -ENOMEM; diff --git a/kerneldriver/core/response_unit/secDetector_ringbuffer.h b/kerneldriver/core/response_unit/secDetector_ringbuffer.h index 252ca9c706f77348277b0770c7a5bc075dba3266..2f78c3f4cbe812eb0a22d77fc59f401764fab7f9 100644 --- a/kerneldriver/core/response_unit/secDetector_ringbuffer.h +++ b/kerneldriver/core/response_unit/secDetector_ringbuffer.h @@ -8,7 +8,7 @@ #ifndef SECDETECTOR_RINGBUFFER_H extern int secDetector_ringbuf_output(const void *data, u64 size, u64 flags); -extern int __init secDetector_ringbuf_dev_init(void); +extern int __init secDetector_ringbuf_dev_init(unsigned int rb_sz); extern void __exit secDetector_ringbuf_dev_exit(void); #define SECDETECTOR_RINGBUFFER_H diff --git a/kerneldriver/core/secDetector_main.c b/kerneldriver/core/secDetector_main.c index e166aaa1005d84819ac5603ddeeea57ac512903b..878d4a391ffb75416e2a7abf6d2165db21b05ad8 100644 --- a/kerneldriver/core/secDetector_main.c +++ b/kerneldriver/core/secDetector_main.c @@ -16,9 +16,37 @@ static unsigned int log_size = 4096; module_param(log_size, uint, 0400); MODULE_PARM_DESC(log_size, "log size"); +#define MIN_RINGBUF_SIZE 4 +#define MAX_RINGBUF_SIZE 1024 + +static unsigned int ringbuf_size = MIN_RINGBUF_SIZE; /* unit is Mb */ +static unsigned int ringbuf_size_bytes; /* unit is bytes */ +module_param(ringbuf_size, uint, 0400); +MODULE_PARM_DESC(log_size, "ringbuffer size"); + +static bool ringbuf_size_check(void) +{ + if (ringbuf_size < MIN_RINGBUF_SIZE || ringbuf_size > MAX_RINGBUF_SIZE) { + pr_err("[secDetector] ringbuf_size should be 4 and 1024 (Mb)\n"); + return false; + } + + if (!is_power_of_2(ringbuf_size)) { + pr_err("[secDetector] ringbuf_size should be power of 2\n"); + return false; + } + + ringbuf_size_bytes = ringbuf_size * 1024 * 1024; + return true; +} + static int __init secDetector_init(void) { int ret; + + if (!ringbuf_size_check()) + return -EINVAL; + ret = secDetector_init_manager(); if (ret != 0) { pr_err("[secDetector] init manager failed\n"); @@ -38,7 +66,7 @@ static int __init secDetector_init(void) return ret; } - ret = secDetector_response_init(); + ret = secDetector_response_init(ringbuf_size_bytes); if (ret != 0) { pr_err("[secDetector] init ringbuf failed\n"); secDetector_destroy_log(); diff --git a/kerneldriver/include/secDetector_response.h b/kerneldriver/include/secDetector_response.h index af832cdbcd246343a96fc7c3f626663f0bdfd844..960ea639069b43c6085f9b5e772dfc943b293b61 100644 --- a/kerneldriver/include/secDetector_response.h +++ b/kerneldriver/include/secDetector_response.h @@ -30,6 +30,6 @@ extern void notrace secDetector_proc_report(response_data_t *log); void free_response_data_no_rd(uint32_t repsonse_id, response_data_t *rd); void free_response_data(uint32_t repsonse_id, response_data_t *rd); -extern int __init secDetector_response_init(void); +extern int __init secDetector_response_init(unsigned int rb_sz); extern void __exit secDetector_response_exit(void); #endif diff --git a/observer_agent/ebpf/fentry.bpf.c b/observer_agent/ebpf/fentry.bpf.c index 9cbc9e6d36f24b78840f31cf02260dad246550ef..f8b8b8781be73acfc14539dbeb58f7fc7521198a 100644 --- a/observer_agent/ebpf/fentry.bpf.c +++ b/observer_agent/ebpf/fentry.bpf.c @@ -28,6 +28,16 @@ struct __uint(max_entries, 1024 * 1024); } rb SEC(".maps"); +const volatile int secdetector_pid = -1; + +#define RETURN_IF_OURSELF(retval) \ +do { \ + if (secdetector_pid == bpf_get_current_pid_tgid() >> 32) \ + return retval; \ +} while(0) + +#define RETURN_ZERO_IF_OURSELF() RETURN_IF_OURSELF(0) + static inline u32 get_task_sid(struct task_struct *task) { struct pid *pid; @@ -77,7 +87,7 @@ static void get_common_info(struct ebpf_event *e) struct task_struct *task = NULL; e->timestamp = bpf_ktime_get_ns(); - e->pid = bpf_get_current_pid_tgid(); + e->pid = bpf_get_current_pid_tgid() >> 32; e->pgid = e->tgid = bpf_get_current_pid_tgid() >> 32; e->uid = bpf_get_current_uid_gid(); e->gid = bpf_get_current_uid_gid() >> 32; @@ -102,6 +112,7 @@ SEC("tp/sched/sched_process_exec") int handle_exec(struct trace_event_raw_sched_process_exec *ctx) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) @@ -120,6 +131,7 @@ int handle_exit(void) { struct ebpf_event *e = NULL; u32 exit_code = 0; + RETURN_ZERO_IF_OURSELF(); e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) @@ -138,6 +150,7 @@ SEC("tp/sched/sched_process_fork") int handle_fork(struct trace_event_raw_sched_process_fork *ctx) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) @@ -153,6 +166,8 @@ int handle_fork(struct trace_event_raw_sched_process_fork *ctx) SEC("fentry/commit_creds") int BPF_PROG(handle_commit_creds, const struct cred *new) { + RETURN_ZERO_IF_OURSELF(); + struct task_struct *task = (struct task_struct *)bpf_get_current_task(); int old_uid = BPF_CORE_READ(task, cred, uid.val); int old_gid = BPF_CORE_READ(task, cred, gid.val); @@ -180,6 +195,7 @@ SEC("fentry/security_bprm_check") int BPF_PROG(handle_bprm_check, struct linux_binprm *bprm) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) diff --git a/observer_agent/ebpf/fentry.c b/observer_agent/ebpf/fentry.c index 35a05fdb87695f6b3aa6b86e9666382651f673a8..c3e026f977b6b0053ee8cc7d09c56aed73eba9f8 100644 --- a/observer_agent/ebpf/fentry.c +++ b/observer_agent/ebpf/fentry.c @@ -32,19 +32,27 @@ void StopProcesseBPFProg() exiting = 1; } -int StartProcesseBPFProg(ring_buffer_sample_fn cb) +int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) { struct fentry_bpf *skel; struct ring_buffer *rb = NULL; int err; /* Open load and verify BPF application */ - skel = fentry_bpf__open_and_load(); + skel = fentry_bpf__open(); if (!skel) { fprintf(stderr, "Failed to open BPF skeleton\n"); return 1; } + bpf_map__set_max_entries(skel->maps.rb, rb_sz); + skel->rodata->secdetector_pid = getpid(); + + if (fentry_bpf__load(skel)) { + fprintf(stderr, "Failed to load BPF skeleton\n"); + err = -1; + goto cleanup; + } /* Attach tracepoint handler */ err = fentry_bpf__attach(skel); diff --git a/observer_agent/ebpf/fentry.h b/observer_agent/ebpf/fentry.h index b5efd6ecc9745889cc8b62f841b14547338f84c4..b0819f3c29bdb7d69acc34a68398ef60998aaa95 100644 --- a/observer_agent/ebpf/fentry.h +++ b/observer_agent/ebpf/fentry.h @@ -22,10 +22,10 @@ extern "C" #include void StopProcesseBPFProg(); -int StartProcesseBPFProg(ring_buffer_sample_fn cb); +int StartProcesseBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz); void StopFileBPFProg(); -int StartFileBPFProg(ring_buffer_sample_fn cb); +int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz); #ifdef __cplusplus } #endif diff --git a/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c b/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c index a0aa6c4e0ab9f3b2edc6f705ef4eb4c2111c9962..d5f72750d1ddf192e837496abc05c8947b9f7990 100644 --- a/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c +++ b/observer_agent/ebpf/file_ebpf/file_fentry.bpf.c @@ -21,6 +21,16 @@ struct __uint(max_entries, 1024 * 1024); } rb SEC(".maps"); +const volatile int secdetector_pid = -1; + +#define RETURN_IF_OURSELF(retval) \ +do { \ + if (secdetector_pid == bpf_get_current_pid_tgid() >> 32) \ + return retval; \ +} while(0) + +#define RETURN_ZERO_IF_OURSELF() RETURN_IF_OURSELF(0) + static inline u32 get_task_sid(struct task_struct *task) { struct pid *pid; @@ -70,7 +80,7 @@ static void get_common_info(struct ebpf_event *e) struct task_struct *task = NULL; e->timestamp = bpf_ktime_get_ns(); - e->pid = bpf_get_current_pid_tgid(); + e->pid = bpf_get_current_pid_tgid() >> 32; e->pgid = e->tgid = bpf_get_current_pid_tgid() >> 32; e->uid = bpf_get_current_uid_gid(); e->gid = bpf_get_current_uid_gid() >> 32; @@ -95,6 +105,7 @@ SEC("fexit/do_filp_open") int BPF_PROG(do_filp_open_exit, int dfd, struct filename *pathname, const struct open_flags *op, struct file *ret_file) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); if (op && !(op->open_flag & O_CREAT)) return 0; @@ -105,7 +116,7 @@ int BPF_PROG(do_filp_open_exit, int dfd, struct filename *pathname, const struct if (!e) return 0; - e->type = 4; + e->type = CREATFILE; get_common_info(e); __builtin_memcpy(e->event_name, "do_filp_open", sizeof("do_filp_open")); bpf_probe_read(e->file_info.filename, MAX_TEXT_SIZE, pathname->name); @@ -119,6 +130,9 @@ int BPF_PROG(fexit_vfs_write, struct file *file, const char *buf, size_t count, struct ebpf_event *e = NULL; if (ret <= 0) return 0; + + RETURN_ZERO_IF_OURSELF(); + if (!S_ISREG(file->f_inode->i_mode)) return 0; @@ -126,7 +140,7 @@ int BPF_PROG(fexit_vfs_write, struct file *file, const char *buf, size_t count, if (!e) return 0; - e->type = 1; + e->type = WRITEFILE; get_common_info(e); __builtin_memcpy(e->event_name, "vfs_write", sizeof("vfs_write")); bpf_probe_read(e->file_info.filename, MAX_TEXT_SIZE, file->f_path.dentry->d_name.name); @@ -143,6 +157,8 @@ int BPF_PROG(fexit_vfs_unlink, struct inode *dir, struct dentry *dentry, struct if (ret != 0) return 0; + RETURN_ZERO_IF_OURSELF(); + e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; @@ -162,12 +178,15 @@ int BPF_PROG(fexit_vfs_read, struct file *file, char *buf, size_t count, long lo if (ret != 0) return 0; + + RETURN_ZERO_IF_OURSELF(); + if (!S_ISREG(file->f_inode->i_mode)) return 0; e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; - e->type = 9; + e->type = READFILE; get_common_info(e); __builtin_memcpy(e->event_name, "vfs_read", sizeof("vfs_read")); bpf_probe_read(e->file_info.filename, MAX_TEXT_SIZE, file->f_path.dentry->d_name.name); @@ -181,6 +200,8 @@ int BPF_PROG(fexit_vfs_utimes, const struct path *path, struct timespec64 *times { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); + e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; @@ -198,6 +219,8 @@ int BPF_PROG(fexit_chmod_common, const struct path *path, umode_t mode, int ret) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); + e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; @@ -215,6 +238,8 @@ int BPF_PROG(fexit_chown_common, const struct path *path, uid_t user, gid_t grou { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); + e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; @@ -232,6 +257,8 @@ int BPF_PROG(fentry__vfs_setxattr_noperm, struct dentry *dentry, const char *nam { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); + e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) return 0; @@ -249,6 +276,7 @@ SEC("fentry/__vfs_removexattr_locked") int BPF_PROG(fentry__vfs_removexattr_locked, struct dentry *dentry, const char *name, struct inode **delegated_inode) { struct ebpf_event *e = NULL; + RETURN_ZERO_IF_OURSELF(); e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0); if (!e) diff --git a/observer_agent/ebpf/file_ebpf/file_fentry.c b/observer_agent/ebpf/file_ebpf/file_fentry.c index c39f0a155f13da5489f9241a193e14a540e5ab3a..8e83723c5e71af9d7857584206f7b6d2be218339 100644 --- a/observer_agent/ebpf/file_ebpf/file_fentry.c +++ b/observer_agent/ebpf/file_ebpf/file_fentry.c @@ -21,19 +21,27 @@ void StopFileBPFProg() exiting = 1; } -int StartFileBPFProg(ring_buffer_sample_fn cb) +int StartFileBPFProg(ring_buffer_sample_fn cb, unsigned int rb_sz) { struct file_fentry_bpf *skel; struct ring_buffer *rb = NULL; int err; /* Open load and verify BPF application */ - skel = file_fentry_bpf__open_and_load(); + skel = file_fentry_bpf__open(); if (!skel) { fprintf(stderr, "Failed to open BPF skeleton\n"); return 1; } + bpf_map__set_max_entries(skel->maps.rb, rb_sz); + skel->rodata->secdetector_pid = getpid(); + + if (file_fentry_bpf__load(skel)) { + fprintf(stderr, "Failed to load BPF skeleton\n"); + err = -1; + goto cleanup; + } /* Attach tracepoint handler */ err = file_fentry_bpf__attach(skel); diff --git a/observer_agent/ebpf/file_ebpf/test_file_fentry.c b/observer_agent/ebpf/file_ebpf/test_file_fentry.c index 3e317de52c779df4c2e9739071a2d24b14770508..3a49a5c043ae403547d717599c3056dda0bf5df2 100644 --- a/observer_agent/ebpf/file_ebpf/test_file_fentry.c +++ b/observer_agent/ebpf/file_ebpf/test_file_fentry.c @@ -26,5 +26,5 @@ int main() { /* Set up libbpf errors and debug info callback */ libbpf_set_print(libbpf_print_fn); - StartFileBPFProg(handle_event); + StartFileBPFProg(handle_event, 4 * 1024 * 1024); } diff --git a/observer_agent/ebpf/test_fentry.c b/observer_agent/ebpf/test_fentry.c index 155ddaef720d850f8cc37fd7df93c751ef1fea51..039153bc94d118155c073e9e87d841aec9fd1071 100644 --- a/observer_agent/ebpf/test_fentry.c +++ b/observer_agent/ebpf/test_fentry.c @@ -39,5 +39,5 @@ int main() { /* Set up libbpf errors and debug info callback */ libbpf_set_print(libbpf_print_fn); - StartProcesseBPFProg(handle_event); + StartProcesseBPFProg(handle_event, 4 * 1024 * 1024); } diff --git a/observer_agent/service/main.cpp b/observer_agent/service/main.cpp index abbbb02ddbb77a8329ad8b92f62edd569ee01443..3e784c7993c04e62b79bf3f892c76dba5ccfd464 100644 --- a/observer_agent/service/main.cpp +++ b/observer_agent/service/main.cpp @@ -40,6 +40,37 @@ using grpc::ServerBuilder; using grpc::ServerContext; using grpc::ServerWriter; +#define MIN_RINGBUF_SIZE 4 +#define MAX_RINGBUF_SIZE 1024 +static unsigned int ringbuf_size_bytes; +static unsigned int ringbuf_size = MIN_RINGBUF_SIZE; + +static bool power_of_2(unsigned int num) +{ + if (num == 0) + return false; + if (num & (num - 1) != 0) + return false; + return true; +} + +static bool ringbuf_size_check(void) +{ + if (ringbuf_size < MIN_RINGBUF_SIZE || ringbuf_size > MAX_RINGBUF_SIZE) { + std::cerr << "[secDetector] ringbuf_size should be 4 and 1024 (Mb)" << std::endl; + return false; + } + + if (!power_of_2(ringbuf_size)) { + std::cerr << "[secDetector] ringbuf_size should be power of 2" << std::endl; + return false; + } + + std::cout << "ringbuf size is set to " << ringbuf_size << "Mb" << std::endl; + ringbuf_size_bytes = ringbuf_size * 1024 * 1024; + return true; +} + static volatile sig_atomic_t exiting = 0; static void sig_handler(int sig) { @@ -91,17 +122,26 @@ int main(int argc, char *argv[]) { int r; int opt; + unsigned int rb_sz; set_signal_handler(); - while ((opt = getopt(argc, argv, "d")) != -1) + while ((opt = getopt(argc, argv, "ds:")) != -1) { switch (opt) { case 'd': debug = true; break; + case 's': + ringbuf_size = strtoul(optarg, NULL, 0); + break; } } + + if (!ringbuf_size_check()) { + std::cerr << "Not a valid ring buffer size" << std::endl; + return -1; + } if (debug) { @@ -125,8 +165,8 @@ int main(int argc, char *argv[]) } std::thread thread_grpc = std::thread(RunServer); - std::thread thread_ebpf_process = std::thread(StartProcesseBPFProg, ebpf_cb); - std::thread thread_ebpf_file = std::thread(StartFileBPFProg, ebpf_cb); + std::thread thread_ebpf_process = std::thread(StartProcesseBPFProg, ebpf_cb, ringbuf_size_bytes); + std::thread thread_ebpf_file = std::thread(StartFileBPFProg, ebpf_cb, ringbuf_size_bytes); while (exiting == 0) {