diff --git a/xpm/core/xpm_hck.c b/xpm/core/xpm_hck.c index faf88030cb0767be13d2a072d92d1097e29c1495..91133eda34b23df850d064d6b672a03d60d182e7 100644 --- a/xpm/core/xpm_hck.c +++ b/xpm/core/xpm_hck.c @@ -125,7 +125,6 @@ static int xpm_check_signature(struct vm_area_struct *vma, unsigned long prot) ret = get_exec_file_signature_info(vma->vm_file, is_exec, &info); if (ret) { xpm_check_signature_error(vma->vm_file, ret); - report_file_event(TYPE_FORMAT_UNDEF, vma->vm_file); return ret; } @@ -153,10 +152,13 @@ static int xpm_check_prot(struct vm_area_struct *vma, unsigned long prot) bool is_anon; is_anon = xpm_is_anonymous_vma(vma); - if ((vma->vm_flags & VM_XPM) && (is_anon || (prot & PROT_WRITE) || - (prot & PROT_EXEC))) { - xpm_log_error("xpm region mmap not allow anonymous/exec/write permission"); - return -EPERM; + if (vma->vm_flags & VM_XPM) { + if(is_anon || (prot & PROT_EXEC)) { + xpm_log_error("xpm region mmap not allow anonymous or exec permission"); + return -EPERM; + } + + return 0; } /* anonymous executable permission need controled by selinux */ diff --git a/xpm/core/xpm_report.c b/xpm/core/xpm_report.c index 202f9f99879d230b9796dbb3578247197e087940..cc3d1cdf514d2385b32bddc25fc3f327de9f0e10 100644 --- a/xpm/core/xpm_report.c +++ b/xpm/core/xpm_report.c @@ -15,6 +15,13 @@ #include "xpm_log.h" #include "xpm_report.h" +#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE) +static char *code_type_tbl[] = { + [TYPE_ABC] = "ABC", + [TYPE_ELF] = "ELF", + [TYPE_ANON] = "ANON" +}; + #ifndef CONFIG_HW_KERNEL_SG typedef struct { unsigned long event_id; @@ -30,9 +37,9 @@ unsigned int report_security_info(const event_info *event) } #endif -static char *xpm_get_filename(struct xpm_event_param *param, char *buf, int len) +static void xpm_set_filename(struct xpm_report_param *param, + struct xpm_report_info *info) { - char *filename = NULL; struct file *file = NULL; if (param->file) @@ -40,25 +47,25 @@ static char *xpm_get_filename(struct xpm_event_param *param, char *buf, int len) else if (param->vma && param->vma->vm_file) file = param->vma->vm_file; else - return NULL; - - filename = d_absolute_path(&file->f_path, buf, len); - if (IS_ERR(filename)) { - xpm_log_error("xpm get absolute path failed"); - return NULL; + return; + + info->filename = file_path(file, info->filename_buf, + sizeof(info->filename_buf) - 1); + if (IS_ERR(info->filename)) { + info->filename = info->filename_buf; + info->filename_buf[0] = "\0"; + xpm_log_error("xpm get file path failed"); } - - return filename; } -static int set_init_content(struct xpm_event_param *param, +static int set_init_content(struct xpm_report_info *info, uint8_t *content, uint32_t content_len) { int len; len = snprintf(content, content_len, "{ "JSTR_PAIR(event_type, %s)", "JVAL_PAIR(timestamp, %llu)" }", - param->event_type, param->timestamp); + info->event_type, info->timestamp); if (len < 0 || len > content_len) { xpm_log_error("snprintf init content failed"); @@ -68,32 +75,25 @@ static int set_init_content(struct xpm_event_param *param, return 0; } -#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE) -const static char *code_type[] = { - [TYPE_ABC] = "ABC", - [TYPE_ELF] = "ELF", - [TYPE_ANON] = "ANON" -}; -static int set_mmap_content(struct xpm_event_param *param, uint8_t *content, +static int set_mmap_content(struct xpm_report_info *info, uint8_t *content, uint32_t content_len) { int len; - if (!param->vma) { + if (!info->vma) { xpm_log_error("input vma is NULL"); return -EINVAL; } len = snprintf(content, content_len, - "{ "JSTR_PAIR(event_type, %s)", "JVAL_PAIR(timestamp, %llu)", " - JVAL_PAIR(pid, %u)", "JSTR_PAIR(filename, %s)", " - JSTR_PAIR(code_type, %s)", "JVAL_PAIR(prot, %lu)"," - JVAL_PAIR(pgoff, %lu)", "JVAL_PAIR(size, %lu)" }", - param->event_type, param->timestamp, param->pid, - param->filename ? param->filename : "", - code_type[param->code], param->prot & PROT_MASK, - param->vma->vm_pgoff, - param->vma->vm_end - param->vma->vm_start); + "{ "JSTR_PAIR(event_type, %s)", "JSTR_PAIR(code_type, %s)", " + JVAL_PAIR(pid, %u)", "JSTR_PAIR(comm, %s)", " + JSTR_PAIR(filename, %s)", "JVAL_PAIR(prot, %lu)"," + JVAL_PAIR(pgoff, %lu)", "JVAL_PAIR(size, %lu)"," + JVAL_PAIR(timestamp, %llu)" }", + info->event_type, info->code_type, info->pid, info->comm, + info->filename, info->prot, info->vma->vm_pgoff, + info->vma->vm_end - info->vma->vm_start, info->timestamp); if (len < 0 || len > content_len) { xpm_log_error("snprintf code mmap content failed"); @@ -103,16 +103,17 @@ static int set_mmap_content(struct xpm_event_param *param, uint8_t *content, return 0; } -static int set_file_content(struct xpm_event_param *param, +static int set_file_content(struct xpm_report_info *info, uint8_t *content, uint32_t content_len) { int len; len = snprintf(content, content_len, - "{ "JSTR_PAIR(event_type, %s)", "JVAL_PAIR(timestamp, %llu)", " - JVAL_PAIR(pid, %u)", "JSTR_PAIR(filename, %s)" }", - param->event_type, param->timestamp, param->pid, - param->filename ? param->filename : ""); + "{ "JSTR_PAIR(event_type, %s)", "JVAL_PAIR(pid, %u)", " + JSTR_PAIR(comm, %s)", "JSTR_PAIR(filename, %s)", " + JVAL_PAIR(timestamp, %llu)" }", + info->event_type, info->pid, info->comm, + info->filename, info->timestamp); if (len < 0 || len > content_len) { xpm_log_error("snprintf file format content failed"); @@ -122,28 +123,28 @@ static int set_file_content(struct xpm_event_param *param, return 0; } -static int set_integrity_content(struct xpm_event_param *param, +static int set_integrity_content(struct xpm_report_info *info, uint8_t *content, uint32_t content_len) { int len; - char *page_type; + char *page_type = NULL; - if (!param->vma || !param->page) { + if (!info->vma || !info->page) { xpm_log_error("input vma or page is NULL"); return -EINVAL; } - page_type = PageKsm(param->page) ? - "[ksm]" : PageAnon(param->page) ? "[anon]" : "[file]"; + page_type = PageKsm(info->page) ? + "[ksm]" : PageAnon(info->page) ? "[anon]" : "[file]"; len = snprintf(content, content_len, - "{ " JSTR_PAIR(event_type, %s)", "JVAL_PAIR(timestamp, %llu)", " - JVAL_PAIR(pid, %u)","JSTR_PAIR(page_type, %s)", " - JSTR_PAIR(filename, %s)", "JVAL_PAIR(page_index, %lu)"," - JVAL_PAIR(page_prot, %lu)" }", - param->event_type, param->timestamp, param->pid, page_type, - param->filename ? param->filename : "", param->page->index, - param->vma->vm_page_prot.pgprot & PROT_MASK); + "{ "JSTR_PAIR(event_type, %s)", "JVAL_PAIR(pid, %u)"," + JSTR_PAIR(comm, %s)", "JSTR_PAIR(filename, %s)", " + JSTR_PAIR(page_type, %s)", "JVAL_PAIR(page_index, %lu)"," + JVAL_PAIR(page_prot, %lu)", "JVAL_PAIR(timestamp, %llu)" }", + info->event_type, info->pid, info->comm, info->filename, + page_type, info->page->index, + info->vma->vm_page_prot.pgprot & PROT_MASK); if (len < 0 || len > content_len) { xpm_log_error("snprintf init integrity failed"); @@ -153,120 +154,138 @@ static int set_integrity_content(struct xpm_event_param *param, return 0; } -static const struct xpm_event_info xpm_event[] = { - [TYPE_DEVICEFS_UNINIT] = { "devicefs uninitialized", - EVENT_INIT, set_init_content }, - [TYPE_DEBUGFS_UNINIT] = { "debugfs uninitialized", - EVENT_INIT, set_init_content }, - [TYPE_DM_DISABLE] = { "dm-verity disable", - EVENT_INIT, set_init_content }, +static struct xpm_event_info xpm_event_tbl[] = { + [TYPE_DEVICEFS_UNINIT] = + { "devicefs uninitialized", EVENT_INIT, set_init_content }, + [TYPE_DEBUGFS_UNINIT] = + { "debugfs uninitialized", EVENT_INIT, set_init_content }, + [TYPE_DM_DISABLE] = + { "dm-verity disable", EVENT_INIT, set_init_content }, [TYPE_FORMAT_UNDEF] = { "unkown file format", EVENT_FILE, set_file_content }, - [TYPE_ANON_EXEC] = { "anon executed", - EVENT_MMAP, set_file_content }, - [TYPE_SIGN_INVALID] = { "invalid signature", - EVENT_MMAP, set_mmap_content }, - [TYPE_DATA_MMAP_CODE] = { "data mmap code", - EVENT_MMAP, set_mmap_content }, - [TYPE_INTEGRITY_RO] = { "code tampered", - EVENT_INTEGRITY, set_integrity_content }, - [TYPE_INTEGRITY_WT] = { "data executed", - EVENT_INTEGRITY, set_integrity_content }, + [TYPE_SIGN_UNAVAILABLE] = + { "unavalible signagure", EVENT_FILE, set_file_content }, + [TYPE_ANON_EXEC] = + { "anon executed", EVENT_MMAP, set_file_content }, + [TYPE_SIGN_INVALID] = + { "invalid signature", EVENT_MMAP, set_mmap_content }, + [TYPE_DATA_MMAP_CODE] = + { "data mmap code", EVENT_MMAP, set_mmap_content }, + [TYPE_INTEGRITY_RO] = + { "code tampered", EVENT_INTEGRITY, set_integrity_content }, + [TYPE_INTEGRITY_WT] = + { "data executed", EVENT_INTEGRITY, set_integrity_content }, }; static int report_event_inner(enum xpm_event_type type, - struct xpm_event_param *param, event_info *event) + struct xpm_report_info *info, event_info *event) { int ret; - ret = xpm_event[type].set_content(param, event->content, + if (!(xpm_event_tbl[type].set_content)) { + xpm_log_error("type [%s] set content func invalid", + xpm_event_tbl[type].event_type); + return -EINVAL; + } + + ret = xpm_event_tbl[type].set_content(info, event->content, MAX_CONTENT_LEN); if (ret) { - xpm_log_error("type [%d] set content failed", type); + xpm_log_error("event type [%s] set content failed", + xpm_event_tbl[type].event_type); return ret; } event->content_len = strlen(event->content); - event->event_id = xpm_event[type].event_id; + event->event_id = xpm_event_tbl[type].event_id; event->version = XPM_EVENT_VERSION; ret = report_security_info(event); if (ret) { - xpm_log_error("type [%d] report security info failed", type); + xpm_log_error("event type [%s] report security info failed", + xpm_event_tbl[type].event_type); return ret; } return 0; } -static int xpm_report_event(enum xpm_event_type type, - struct xpm_event_param *param) +static int xpm_report_event(struct xpm_report_param *param) { int ret; - event_info *sg_event; - char *buf; + event_info *sg_event = NULL; + struct xpm_report_info *info = NULL; - if (!(xpm_event[type].set_content)) { - xpm_log_error("type [%d] set content func invalid", type); - return -EINVAL; + info = kzalloc(sizeof(struct xpm_report_info), GFP_ATOMIC); + if (!info) { + xpm_log_error("alloc xpm report info failed"); + return -ENOMEM; } - sg_event = kzalloc(sizeof(event_info) + MAX_CONTENT_LEN, GFP_KERNEL); + sg_event = kzalloc(sizeof(event_info) + MAX_CONTENT_LEN, + GFP_ATOMIC); if (!sg_event) { xpm_log_error("alloc security guard event failed"); + kfree(info); return -ENOMEM; } - buf = __getname(); - if (!buf) { - xpm_log_error("alloc file name buf failed"); - kfree(sg_event); - return -ENOMEM; - } - - param->event_type = xpm_event[type].event_type; - param->filename = xpm_get_filename(param, buf, PATH_MAX); - param->timestamp = ktime_get_real_seconds(); - param->pid = current->pid; - - ret = report_event_inner(type, param, sg_event); - - __putname(buf); + info->event_type = xpm_event_tbl[param->type].event_type; + info->code_type = code_type_tbl[param->code_type]; + info->vma = param->vma; + info->page = param->page; + info->prot = param->prot & PROT_MASK; + info->pid = current->pid; + memcpy(info->comm, current->comm, TASK_COMM_LEN); + xpm_set_filename(param, info); + info->timestamp = ktime_get_real_seconds(); + + ret = report_event_inner(param->type, info, sg_event); + kfree(info); kfree(sg_event); + return ret; } void report_init_event(enum xpm_event_type type) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = { + .type = type, + }; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + xpm_report_ratelimited(xpm_report_event, ¶m); } void report_file_event(enum xpm_event_type type, struct file *file) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = { + .type = type, + .file = file, + }; - param.file = file; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + xpm_report_ratelimited(xpm_report_event, ¶m); } void report_mmap_event(enum xpm_event_type type, struct vm_area_struct *vma, - int code, int prot) + int code_type, int prot) { - struct xpm_event_param param = {0}; - - param.vma = vma; - param.code = code; - param.prot = prot; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + struct xpm_report_param param = { + .type = type, + .vma = vma, + .code_type = code_type, + .prot = prot, + }; + + xpm_report_ratelimited(xpm_report_event, ¶m); } void report_integrity_event(enum xpm_event_type type, struct vm_area_struct *vma, struct page *page) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = { + .type = type, + .vma = vma, + .page = page, + }; - param.vma = vma; - param.page = page; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + xpm_report_ratelimited(xpm_report_event, ¶m); } diff --git a/xpm/include/xpm_report.h b/xpm/include/xpm_report.h index aff1f67d71a89d8c18129bb1073c64371bbb40df..a679bc01e5762880493e2992181865233d2bcdf6 100644 --- a/xpm/include/xpm_report.h +++ b/xpm/include/xpm_report.h @@ -9,6 +9,8 @@ #include #include +#define MAX_FILENAME_BUF_LEN 128 + enum xpm_event_id { EVENT_INIT = 1011009110, EVENT_FILE = 1011009111, @@ -21,6 +23,7 @@ enum xpm_event_type { TYPE_DEBUGFS_UNINIT, TYPE_DM_DISABLE, TYPE_FORMAT_UNDEF, + TYPE_SIGN_UNAVAILABLE, TYPE_ANON_EXEC, TYPE_SIGN_INVALID, TYPE_DATA_MMAP_CODE, @@ -29,29 +32,39 @@ enum xpm_event_type { }; enum { - TYPE_ABC, + TYPE_ABC = 0, TYPE_ELF, TYPE_ANON, }; -struct xpm_event_param { +struct xpm_report_param { + enum xpm_event_type type; + uint32_t event_type; + uint32_t code_type; + struct vm_area_struct *vma; + struct page *page; + struct file *file; + unsigned long prot; +}; + +struct xpm_report_info { char *event_type; - char *filename; - ktime_t timestamp; + char *code_type; pid_t pid; - + char comm[TASK_COMM_LEN]; + char filename_buf[MAX_FILENAME_BUF_LEN]; + char *filename; struct vm_area_struct *vma; struct page *page; - struct file *file; - int code; unsigned long prot; + ktime_t timestamp; }; struct xpm_event_info { char *event_type; enum xpm_event_id event_id; - int (*set_content)(struct xpm_event_param *param, uint8_t *content, - uint32_t content_len); + int (*set_content)(struct xpm_report_info *info, + uint8_t *content, uint32_t content_len); }; #define MAX_CONTENT_LEN 900 @@ -79,7 +92,7 @@ struct xpm_event_info { void report_init_event(enum xpm_event_type type); void report_file_event(enum xpm_event_type type, struct file *file); void report_mmap_event(enum xpm_event_type type, struct vm_area_struct *vma, - int code, int prot); + int code_type, int prot); void report_integrity_event(enum xpm_event_type type, struct vm_area_struct *vma, struct page *page); diff --git a/xpm/validator/exec_signature_info.c b/xpm/validator/exec_signature_info.c index 17faa68999fdc25fd20f4f54de8d5f5a93b37f99..e7da7c63fe7aca409c840ba8251c3c73b50e861a 100644 --- a/xpm/validator/exec_signature_info.c +++ b/xpm/validator/exec_signature_info.c @@ -494,8 +494,10 @@ static int get_elf_code_segment_info(struct file *file, bool is_exec, int type, struct exec_file_signature_info *new_info; struct exec_file_signature_info *old_info; - if (get_verity_info(type, &verity) < 0) - return -EINVAL; + if (get_verity_info(type, &verity) < 0) { + report_file_event(TYPE_SIGN_UNAVAILABLE, file); + return 0; + } file_node = file_inode(file); if (file_node == NULL) @@ -521,8 +523,10 @@ need_parse: return -ENOMEM; } else { ret = parse_elf_code_segment_info(file, &new_info); - if (ret < 0) + if (ret < 0) { + report_file_event(TYPE_FORMAT_UNDEF, file); return ret; + } #ifdef CONFIG_SECURITY_XPM_DEBUG test_print_info(file, type, new_info); #endif