diff --git a/kerneldriver/core/hook_unit/secDetector_hook.c b/kerneldriver/core/hook_unit/secDetector_hook.c index 1c478b124a4f413d109b1be0a4e0838cbbcf48ee..d3ae696454540b09f57a83b431b7d1eac92e7779 100644 --- a/kerneldriver/core/hook_unit/secDetector_hook.c +++ b/kerneldriver/core/hook_unit/secDetector_hook.c @@ -29,7 +29,7 @@ struct hook_list_func { static int insert_timer_callback(struct secDetector_workflow *workflow); static int unlink_timer_callback(struct secDetector_workflow *workflow); -static int timer_callback_exists(struct secDetector_workflow *workflow); +static bool timer_callback_exists(struct secDetector_workflow *workflow); static struct hook_list_func hook_list_funcs[] = { { diff --git a/kerneldriver/core/hook_unit/secDetector_hook_tracepoint.c b/kerneldriver/core/hook_unit/secDetector_hook_tracepoint.c index f8bde7c8a6228728c9c368840108bec24c442f23..c25312ad4a0250f206ce72683298ef302c260bc7 100644 --- a/kerneldriver/core/hook_unit/secDetector_hook_tracepoint.c +++ b/kerneldriver/core/hook_unit/secDetector_hook_tracepoint.c @@ -69,7 +69,7 @@ static struct secDetector_tracepoint secDetector_tracepoint_hook_functions[] = { .register_func = NULL, .unregister_func = NULL, } -} +}; int insert_tracepoint_hook(struct secDetector_workflow *workflow) { @@ -83,7 +83,7 @@ int insert_tracepoint_hook(struct secDetector_workflow *workflow) if (workflow->hook_type < TRACEPOINT_HOOK_START || workflow->hook_type > TRACEPOINT_HOOK_END) return -1; - head = &secDetector_hook_array[workflow->hooktype]; + head = &secDetector_hook_array[workflow->hook_type]; if (list_empty(head) == 1) { tp = &secDetector_tracepoint_hook_functions[workflow->hook_type - TRACEPOINT_HOOK_START]; if (tp == NULL || tp->register_func == NULL || tp->handler == NULL) @@ -94,7 +94,7 @@ int insert_tracepoint_hook(struct secDetector_workflow *workflow) return ret; } - list_add_rcu(&workflow->list, &secDetector_hook_array[workflow->hooktype]); + list_add_rcu(&workflow->list, &secDetector_hook_array[workflow->hook_type]); return ret; } @@ -113,7 +113,7 @@ int delete_tracepoint_hook(struct secDetector_workflow *workflow) list_del_rcu(&workflow->list); synchronize_rcu(); - if (list_empty(&secDetector_hook_array[workflow->hooktype]) == 1) { + if (list_empty(&secDetector_hook_array[workflow->hook_type]) == 1) { tp = &secDetector_tracepoint_hook_functions[workflow->hook_type - TRACEPOINT_HOOK_START]; if (tp == NULL || tp->register_func == NULL || tp->handler == NULL) return -1; @@ -134,7 +134,7 @@ bool tracepoint_exists(struct secDetector_workflow *workflow) if (workflow->hook_type < TRACEPOINT_HOOK_START || workflow->hook_type > TRACEPOINT_HOOK_END) return -1; - head = &secDetector_hook_array[workflow->hooktype]; + head = &secDetector_hook_array[workflow->hook_type]; list_for_each_entry(tmp_wf, head, list) { if (tmp_wf == workflow) return true; diff --git a/kerneldriver/core/response_unit/secDetector_proc.c b/kerneldriver/core/response_unit/secDetector_proc.c new file mode 100644 index 0000000000000000000000000000000000000000..53f488cb1ee46121bee25a771e8ceca8cf3b24f0 --- /dev/null +++ b/kerneldriver/core/response_unit/secDetector_proc.c @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. All rights reserved. + * secDetector is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + * Author: zcfsite + * create: 2023-09-22 + * Description: secDetector proc log + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "secDetector_proc.h" + +#define ALARM_RECORDS_MAX_SIZE 4096 +#define ALARM_FILE "alarm" +#define ALARM_FILE_MASK 0600 +#define MSG_ALIGN 4 +#define MSG_LEN 4096 + +static struct proc_dir_entry *g_proc_alarm; +s_secDetector_log *g_secDetector_log_fifo = NULL; + +static int clean_log_fifo_data(void) +{ + int ret; + unsigned int len; + s_log_data log = {0, NULL}; + + if (!g_secDetector_log_fifo || !g_secDetector_log_fifo->inflag) + return 0; + + g_secDetector_log_fifo->inflag = false; + len = kfifo_len(&g_secDetector_log_fifo->log_fifo); + while (len != 0) { + ret = kfifo_out_spinlocked(&g_secDetector_log_fifo->log_fifo, &log, 1, &g_secDetector_log_fifo->log_fifo_lock); + if (ret != 1) { + g_secDetector_log_fifo->inflag = true; + return -1; + } + len = kfifo_len(&g_secDetector_log_fifo->log_fifo); + kfree(log.data); + } + + g_secDetector_log_fifo->inflag = true; + return 0; +} + +static int check_and_out_log_fifo(void) +{ + int ret; + unsigned int avail_len; + s_log_data log = {0, NULL}; + + avail_len = kfifo_len(&g_secDetector_log_fifo->log_fifo); + while (avail_len == 0) { + ret = kfifo_out_spinlocked(&g_secDetector_log_fifo->log_fifo, &log, 1, &g_secDetector_log_fifo->log_fifo_lock); + if (ret != 1) + return -1; + avail_len = kfifo_len(&g_secDetector_log_fifo->log_fifo); + kfree(log.data); + } + return 0; +} + +int write_log(const char *buf, unsigned int buf_len) +{ + int ret; + s_log_data log; + int len; + + if (!buf || buf_len == 0 || buf_len > MSG_LEN) + return -EINVAL; + if (!g_secDetector_log_fifo || !g_secDetector_log_fifo->inflag) + return -1; + + ret = check_and_out_log_fifo(); + if (ret != 0) + return -1; + + log.data_size = buf_len; + log.data = (char *) kzalloc(buf_len, GFP_ATOMIC); + if (!log.data) + return -1; + + len = (buf_len == MSG_LEN) ? buf_len - 1 : buf_len; + memcpy(log.data, buf, len); + + ret = kfifo_out_spinlocked(&g_secDetector_log_fifo->log_fifo, &log, 1, &g_secDetector_log_fifo->log_fifo_lock); + if (ret != 1) { + kfree(log.data); + return -1; + } + + return 0; +} + +static int log_data_to_user(char __user *buffer, size_t buflen, s_log_data *log) +{ + int ret; + if (!log || buflen < log->data_size) + return -1; + + ret = copy_to_user(buffer, log->data, log->data_size); + if (ret != 0) + return -EFAULT; + + return log->data_size; +} + +static ssize_t secDetector_log_read(struct file *file, char __user *buffer, size_t buflen, loff_t *fpos) +{ + int ret; + unsigned int read_len; + bool empty = false; + s_log_data log = {0, NULL}; + + if ((buflen == 0) || (buflen % MSG_ALIGN)) + return -EINVAL; + + empty = kfifo_is_empty(&g_secDetector_log_fifo->log_fifo); + if (empty) + return 0; + + read_len = kfifo_out_spinlocked(&g_secDetector_log_fifo->log_fifo, &log, 1, &g_secDetector_log_fifo->log_fifo_lock); + if (read_len != 1) + return -1; + + ret = log_data_to_user(buffer, buflen, &log); + if (log.data) + kfree(log.data); + + return ret; +} + +static ssize_t secDetector_log_write(struct file *filp, const char __user *buffer, size_t count, loff_t *ppos) +{ + int ret; + if (count != 1) + return (ssize_t)-EINVAL; + + ret = clean_log_fifo_data(); + if (ret != 0) + return ret; + + return count; +} + +static const struct proc_ops g_proc_log_file_operations = { + .proc_read = secDetector_log_read, + .proc_write = secDetector_log_write, + .proc_lseek = no_llseek, +}; + +static int create_log(size_t log_size, struct proc_dir_entry *parent) +{ + int ret; + unsigned int avail_len; + + g_secDetector_log_fifo = kzalloc(sizeof(s_secDetector_log), GFP_KERNEL); + if (!g_secDetector_log_fifo) + return -1; + + spin_lock_init(&g_secDetector_log_fifo->log_fifo_lock); + g_secDetector_log_fifo->inflag = true; + + INIT_KFIFO(g_secDetector_log_fifo->log_fifo); + ret = kfifo_alloc(&g_secDetector_log_fifo->log_fifo, log_size, GFP_KERNEL); + if (ret != 0) { + kfree(g_secDetector_log_fifo); + g_secDetector_log_fifo = NULL; + return -1; + } + + avail_len = kfifo_avail(&g_secDetector_log_fifo->log_fifo); + g_proc_alarm = proc_create(ALARM_FILE, ALARM_FILE_MASK, parent, &g_proc_log_file_operations); + if (!g_proc_alarm) { + kfifo_free(&g_secDetector_log_fifo->log_fifo); + kfree(g_secDetector_log_fifo); + g_secDetector_log_fifo = NULL; + return -1; + } + + return 0; +} + +void secDetector_destroy_log(void) +{ + int ret; + if (g_proc_alarm) { + proc_remove(g_proc_alarm); + g_proc_alarm = NULL; + } + + if (g_secDetector_log_fifo) { + ret = clean_log_fifo_data(); + if (ret != 0) + return; + kfifo_free(&g_secDetector_log_fifo->log_fifo); + kfree(g_secDetector_log_fifo); + g_secDetector_log_fifo = NULL; + } +} + +int __init secDetector_init_log(struct proc_dir_entry *parent, size_t log_size) +{ + int ret; + + if (!parent || log_size <= 1 || log_size > ALARM_RECORDS_MAX_SIZE) + return -EINVAL; + + if (log_size != roundup_pow_of_two(log_size)) { + pr_err("[secDetector] init log_size roundup error, suggest log_size=%zu\n", roundup_pow_of_two(log_size)); + return -EINVAL; + } + + ret = create_log(log_size, parent); + if (ret != 0) { + pr_err("[secDetector] init log error"); + return ret; + } + + return ret; +} diff --git a/kerneldriver/core/response_unit/secDetector_proc.h b/kerneldriver/core/response_unit/secDetector_proc.h new file mode 100644 index 0000000000000000000000000000000000000000..c19bb4e031c560660e5579ab8e143525e9889015 --- /dev/null +++ b/kerneldriver/core/response_unit/secDetector_proc.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Huawei Technologies Co., Ltd. All rights reserved. + * secDetector is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + * + */ + +#ifndef SECDETECTOR_PROC_H +#define SECDETECTOR_PROC_H +#include +#include +#include + +typedef struct secDetector_log_data { + unsigned int data_size; + char *data; +} s_log_data; + +typedef struct secDetector_log { + DECLARE_KFIFO_PTR(log_fifo, s_log_data); + spinlock_t log_fifo_lock; + bool inflag; +} s_secDetector_log; + +extern int __init secDetector_init_log(struct proc_dir_entry *parent, size_t log_size); +extern void secDetector_destroy_log(void); +extern int write_log(const char*buf, unsigned int buf_len); + +#endif diff --git a/kerneldriver/core/response_unit/secDetector_response.c b/kerneldriver/core/response_unit/secDetector_response.c index f62547cc7826ff9151a918b61ac20b3681780d45..164c5c6573cff1df197efa1674efb75e7a8b7717 100644 --- a/kerneldriver/core/response_unit/secDetector_response.c +++ b/kerneldriver/core/response_unit/secDetector_response.c @@ -13,7 +13,9 @@ * Create: 2023-09-21 * Description: secDetector response source */ +#include #include "secDetector_response.h" +#include "secDetector_proc.h" static const response_func_t response_units[NR_RESPONSE] = { [RESPONSE_REPORT] = secdetector_report, @@ -29,5 +31,17 @@ void notrace secdetector_respond(unsigned int response_type, response_data_t *da void notrace secdetector_report(response_data_t *data) { - pr_info("%s", data->report_data.text); -} \ No newline at end of file + pr_info("%s", data->report_data->text); +} + +void notrace secDetector_proc_report(response_data_t *log) +{ + int ret; + if (!log || !log->report_data || !log->report_data->text) + return; + + ret = write_log(log->report_data->text, log->report_data->len); + if (ret != 0) + pr_warn("write_log failed"); +} +EXPORT_SYMBOL_GPL(secDetector_proc_report); diff --git a/kerneldriver/core/secDetector_main.c b/kerneldriver/core/secDetector_main.c index 7c2c7d6138859da5fd97676f53fa70bc6db6a9d9..91252aa5b4e73ac1b6f39ecef59f866e81d54aca 100644 --- a/kerneldriver/core/secDetector_main.c +++ b/kerneldriver/core/secDetector_main.c @@ -23,7 +23,7 @@ struct proc_dir_entry *g_root_dir; static unsigned int log_size = 4096; -module_param(log_size, unit, 0400); +module_param(log_size, uint, 0400); MODULE_PARM_DESC(log_size, "log size"); static int __init secDetector_init(void) @@ -49,7 +49,7 @@ static int __init secDetector_init(void) static void __exit secDetector_exit(void) { - secDector_destroy_log(); + secDetector_destroy_log(); proc_remove(g_root_dir); pr_debug("[secDetector] exit success\n"); diff --git a/kerneldriver/include/secDetector_manager.h b/kerneldriver/include/secDetector_manager.h index f374724d171c368920bf54504a65cc2e84f3cdaa..f64b5f6df8e1fb99b5414f23739604df62491630 100644 --- a/kerneldriver/include/secDetector_manager.h +++ b/kerneldriver/include/secDetector_manager.h @@ -42,7 +42,7 @@ struct secDetector_workflow { struct list_head list; struct rcu_head rcu; unsigned int id; - struct seDetector_module *module; + struct secDetector_module *module; atomic_t enabled; unsigned int hook_type; @@ -64,6 +64,6 @@ struct secDetector_module { extern void secDetector_init_manager(void); extern int secDetector_module_register(struct secDetector_module *module); -extern int secDetector_module_unregister(struct secDetector_module *module); +extern void secDetector_module_unregister(struct secDetector_module *module); #endif diff --git a/kerneldriver/include/secDetector_response.h b/kerneldriver/include/secDetector_response.h index 1c4565e910398502b1d1e9442e985aa6e989814f..e91d4db94453173eee25947894d94a2ab842bf87 100644 --- a/kerneldriver/include/secDetector_response.h +++ b/kerneldriver/include/secDetector_response.h @@ -19,4 +19,7 @@ extern void notrace secdetector_respond(unsigned int response_type, response_data_t *data); extern void notrace secdetector_report(response_data_t *data); -#endif \ No newline at end of file + +// support max 4095 bytes, +extern void notrace secDetector_proc_report(response_data_t *log); +#endif