From 4f26528062f452794573281be09782683daaf109 Mon Sep 17 00:00:00 2001 From: limerence Date: Wed, 22 Nov 2023 22:13:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=86=85=E6=A0=B8=E6=94=AF=E6=8C=81=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E6=89=80=E6=9C=89=E8=80=85=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: limerence --- code_sign/Makefile | 2 +- code_sign/code_sign_elf.c | 2 +- code_sign/code_sign_ext.c | 23 ++ code_sign/code_sign_ext.h | 33 ++ code_sign/code_sign_ioctl.c | 4 +- code_sign/code_sign_misc.c | 4 + code_sign/verify_cert_chain.c | 46 ++- code_sign/verify_cert_chain.h | 6 +- xpm/Kconfig | 3 +- xpm/Makefile | 15 +- xpm/core/xpm_common.c | 11 + xpm/core/xpm_common.h | 23 ++ xpm/core/xpm_debugfs.c | 12 +- xpm/{include => core}/xpm_debugfs.h | 16 +- xpm/core/{xpm_hck.c => xpm_hck_hooks.c} | 253 ++---------- .../xpm_hck.h => core/xpm_hck_hooks.h} | 10 +- xpm/{include => core}/xpm_log.h | 2 - xpm/core/{xpm_misc.c => xpm_misc_device.c} | 99 +++-- .../xpm_misc.h => core/xpm_misc_device.h} | 19 +- xpm/core/xpm_module.c | 18 +- xpm/core/xpm_report.c | 314 ++++++++------- xpm/{include => core}/xpm_report.h | 95 +++-- xpm/core/xpm_security_hooks.c | 373 ++++++++++++++++++ xpm/core/xpm_security_hooks.h | 11 + xpm/{core => developer}/dsmm_developer.c | 40 +- xpm/{include => developer}/dsmm_developer.h | 35 +- xpm/validator/exec_signature_info.c | 14 +- .../exec_signature_info.h | 0 28 files changed, 961 insertions(+), 522 deletions(-) mode change 100755 => 100644 xpm/Kconfig mode change 100755 => 100644 xpm/Makefile create mode 100644 xpm/core/xpm_common.c create mode 100644 xpm/core/xpm_common.h mode change 100755 => 100644 xpm/core/xpm_debugfs.c rename xpm/{include => core}/xpm_debugfs.h (54%) mode change 100755 => 100644 rename xpm/core/{xpm_hck.c => xpm_hck_hooks.c} (40%) rename xpm/{include/xpm_hck.h => core/xpm_hck_hooks.h} (51%) rename xpm/{include => core}/xpm_log.h (95%) rename xpm/core/{xpm_misc.c => xpm_misc_device.c} (50%) mode change 100755 => 100644 rename xpm/{include/xpm_misc.h => core/xpm_misc_device.h} (41%) mode change 100755 => 100644 mode change 100755 => 100644 xpm/core/xpm_module.c rename xpm/{include => core}/xpm_report.h (42%) create mode 100644 xpm/core/xpm_security_hooks.c create mode 100644 xpm/core/xpm_security_hooks.h rename xpm/{core => developer}/dsmm_developer.c (76%) rename xpm/{include => developer}/dsmm_developer.h (36%) rename xpm/{include => validator}/exec_signature_info.h (100%) diff --git a/code_sign/Makefile b/code_sign/Makefile index 6ff0380..8a2af5b 100644 --- a/code_sign/Makefile +++ b/code_sign/Makefile @@ -12,7 +12,7 @@ ccflags-$(CONFIG_SECURITY_CODE_SIGN) += \ -I$(srctree)/fs/code_sign \ -I$(srctree)/security/selinux/include \ -I$(srctree)/security/selinux \ - -I$(srctree)/security/xpm/include + -I$(srctree)/security/xpm/developer $(addprefix $(obj)/,$(obj-y)): $(obj)/flask.h diff --git a/code_sign/code_sign_elf.c b/code_sign/code_sign_elf.c index 65756a6..93c33d8 100644 --- a/code_sign/code_sign_elf.c +++ b/code_sign/code_sign_elf.c @@ -176,7 +176,7 @@ out: int elf_file_enable_fs_verity(struct file *file) { /* developer mode */ - if (strcmp(developer_mode_state(), DEVELOPER_STATUS_ON)) { + if (get_developer_mode_state() != STATE_ON) { code_sign_log_info("developer mode off, elf not allowed to execute"); return -EINVAL; } diff --git a/code_sign/code_sign_ext.c b/code_sign/code_sign_ext.c index c5d2126..afe0422 100644 --- a/code_sign/code_sign_ext.c +++ b/code_sign/code_sign_ext.c @@ -5,10 +5,13 @@ #include #include +#include #include "code_sign_ext.h" #include "code_sign_log.h" +static time64_t cs_salt; + /** * Validate code sign descriptor * @@ -82,3 +85,23 @@ void code_sign_after_measurement(void *_desc, int version) desc->version = version; } } + +void code_sign_init_salt(void) +{ + cs_salt = ktime_get_real_seconds(); +} + +void code_sign_set_ownerid(struct cs_info *cs_info, uint32_t id_type, + const char *id_str, uint32_t id_len) +{ + if (!cs_info) { + code_sign_log_error("Input cs_info is NULL"); + return; + } + + cs_info->id_type = id_type; + if (!id_str || id_len == 0) + cs_info->ownerid = 0; + else + cs_info->ownerid = full_name_hash(cs_salt, id_str, id_len); +} \ No newline at end of file diff --git a/code_sign/code_sign_ext.h b/code_sign/code_sign_ext.h index d424907..2eae677 100644 --- a/code_sign/code_sign_ext.h +++ b/code_sign/code_sign_ext.h @@ -6,6 +6,34 @@ #ifndef _CODE_SIGN_EXT_H #define _CODE_SIGN_EXT_H +#include + +#define OWNERID_SYSTEM_TAG "SYSTEM_LIB_ID" +#define OWNERID_DEBUG_TAG "DEBUG_LIB_ID" +#define OWNERID_SHARED_TAG "SHARED_LIB_ID" +#define OWNERID_COMPAT_TAG "COMPAT_LIB_ID" + +enum file_ownerid_type { + FILE_OWNERID_UNINT = 0, + FILE_OWNERID_SYSTEM, + FILE_OWNERID_APP, + FILE_OWNERID_DEBUG, + FILE_OWNERID_SHARED, + FILE_OWNERID_COMPAT, + FILE_OWNERID_MAX +}; + +/* process and file ownerid types need to correspond to each other */ +enum process_ownerid_type { + PROCESS_OWNERID_UNINIT = FILE_OWNERID_UNINT, + PROCESS_OWNERID_SYSTEM = FILE_OWNERID_SYSTEM, + PROCESS_OWNERID_APP = FILE_OWNERID_APP, + PROCESS_OWNERID_DEBUG = FILE_OWNERID_DEBUG, + PROCESS_OWNERID_COMPAT = FILE_OWNERID_COMPAT, + PROCESS_OWNERID_EXTEND, + PROCESS_OWNERID_MAX +}; + /* * code_sign_ext.c */ @@ -16,4 +44,9 @@ void code_sign_before_measurement(void *_desc, int *ret); void code_sign_after_measurement(void *_desc, int version); +void code_sign_init_salt(void); + +void code_sign_set_ownerid(struct cs_info *cs_info, uint32_t id_type, + const char *id_str, uint32_t id_len); + #endif /* _CODE_SIGN_H */ diff --git a/code_sign/code_sign_ioctl.c b/code_sign/code_sign_ioctl.c index 003ae57..afec635 100644 --- a/code_sign/code_sign_ioctl.c +++ b/code_sign/code_sign_ioctl.c @@ -9,7 +9,7 @@ #include #include "avc.h" #include "objsec.h" -#include "../../security/xpm/include/dsmm_developer.h" +#include "dsmm_developer.h" #include "code_sign_ioctl.h" #include "code_sign_log.h" @@ -231,7 +231,7 @@ int code_sign_check_code(int code) return is_dev_mode; // developer mode - if (!strcmp(developer_mode_state(), DEVELOPER_STATUS_ON)) { + if (get_developer_mode_state() == STATE_ON) { code_sign_log_debug("developer mode on"); is_dev_mode = 1; } diff --git a/code_sign/code_sign_misc.c b/code_sign/code_sign_misc.c index 0fe17ee..ffa02a0 100644 --- a/code_sign/code_sign_misc.c +++ b/code_sign/code_sign_misc.c @@ -37,6 +37,10 @@ static void code_sign_register_hck_hooks(void) static int __init code_sign_init(void) { code_sign_log_info("INIT"); + + /* init module init real time as salt for ownerid calculate */ + code_sign_init_salt(); + code_sign_register_hck_hooks(); return misc_register(&code_sign_misc); } diff --git a/code_sign/verify_cert_chain.c b/code_sign/verify_cert_chain.c index 50d71c8..2409a7e 100644 --- a/code_sign/verify_cert_chain.c +++ b/code_sign/verify_cert_chain.c @@ -9,7 +9,8 @@ #include #include #include "objsec.h" -#include "../../security/xpm/include/dsmm_developer.h" +#include "dsmm_developer.h" +#include "code_sign_ext.h" #include "code_sign_ioctl.h" #include "code_sign_log.h" #include "verify_cert_chain.h" @@ -62,6 +63,43 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7, return 0; } +static void set_file_ownerid(struct cs_info *cs_info, int path_type, + struct pkcs7_signed_info *sinfo) +{ + /* Mark a debug file as OWNERID_DEBUG */ + if((path_type > DEBUG_CODE_START) && (path_type < DEBUG_CODE_END)) { + code_sign_set_ownerid(cs_info, FILE_OWNERID_DEBUG, NULL, 0); + return; + } + + /* Mark the file as OWNERID_COMPAT, if its ownerid is empty */ + if(!sinfo->ownerid) { + code_sign_set_ownerid(cs_info, FILE_OWNERID_COMPAT, NULL, 0); + return; + } + + /* Mark the file as OWNERID_SHARED, if the file is shareable */ + if((sinfo->ownerid_len == strlen(OWNERID_SHARED_TAG)) && + !memcmp(sinfo->ownerid, OWNERID_SHARED_TAG, + sinfo->ownerid_len)) { + code_sign_set_ownerid(cs_info, FILE_OWNERID_SHARED, NULL, 0); + return; + } + + /* If this code is signed on the device, check whether it is DEBUG_ID */ + if((path_type = MAY_LOCAL_CODE) && + (sinfo->ownerid_len == strlen(OWNERID_DEBUG_TAG)) && + !memcmp(sinfo->ownerid, OWNERID_DEBUG_TAG, + sinfo->ownerid_len)) { + code_sign_set_ownerid(cs_info, FILE_OWNERID_DEBUG, NULL, 0); + return; + } + + /* Mark the file OWNERID_APP in other cases */ + code_sign_set_ownerid(cs_info, FILE_OWNERID_APP, + sinfo->ownerid, sinfo->ownerid_len); +} + static struct cert_source *find_matched_source(const struct x509_certificate *signer, bool is_debug) { int block_type = is_debug ? DEBUG_BLOCK_CODE: RELEASE_BLOCK_CODE; @@ -76,7 +114,8 @@ static struct cert_source *find_matched_source(const struct x509_certificate *si return source; } -void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, int *ret) +void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, + struct cs_info *cs_info, int *ret) { struct pkcs7_message *pkcs7; struct pkcs7_signed_info *sinfo; @@ -103,7 +142,7 @@ void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, int *re bool is_dev_mode = false; // developer mode && developer proc - if (!strcmp(developer_mode_state(), DEVELOPER_STATUS_ON)) { + if (get_developer_mode_state() == STATE_ON) { code_sign_log_info("developer mode on"); is_dev_mode = true; } @@ -157,6 +196,7 @@ void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, int *re } if (cert_chain_depth_without_root == (source->max_path_depth - 1)) { code_sign_log_info("cert subject and issuer trusted"); + set_file_ownerid(cs_info, source->path_type, pkcs7->signed_infos); *ret = source->path_type; goto exit; } else { diff --git a/code_sign/verify_cert_chain.h b/code_sign/verify_cert_chain.h index 49b8d6d..eb5a8dd 100644 --- a/code_sign/verify_cert_chain.h +++ b/code_sign/verify_cert_chain.h @@ -6,10 +6,12 @@ #ifndef _VERIFY_CERT_CHAIN_H #define _VERIFY_CERT_CHAIN_H +#include + /* * verify_cert_chain.c */ - -void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, int *ret); +void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, + struct cs_info *cs_info, int *ret); #endif /* _VERIFY_CERT_CHAIN_H */ diff --git a/xpm/Kconfig b/xpm/Kconfig old mode 100755 new mode 100644 index e74ba0d..fbb755a --- a/xpm/Kconfig +++ b/xpm/Kconfig @@ -9,6 +9,7 @@ menu "Executable permission manager" config SECURITY_XPM def_bool $(success, $(srctree)/scripts/ohos-check-dir.sh $(srctree)/security/xpm) depends on 64BIT + depends on SECURITY_CODE_SIGN help The Executable Permission Manager(XPM) control process execution by inserting control poliy into the security hook list, such as execv, @@ -22,7 +23,7 @@ config DSMM_DEVELOPER_ENABLE help This option should only be enabled for the device support developer mode feature. But whether or not developer mode is enabled on the - device ultimately depends on the developer_mode valude in cmdline. + device ultimately depends on the developer_mode string in cmdline. config SECURITY_XPM_DEBUG bool "Enables excutable permission manager debug mode" diff --git a/xpm/Makefile b/xpm/Makefile old mode 100755 new mode 100644 index ae717fb..3fddf33 --- a/xpm/Makefile +++ b/xpm/Makefile @@ -6,22 +6,27 @@ # obj-$(CONFIG_SECURITY_XPM) += \ + core/xpm_common.o \ core/xpm_module.o \ - core/xpm_misc.o \ - core/xpm_hck.o \ + core/xpm_misc_device.o \ + core/xpm_hck_hooks.o \ + core/xpm_security_hooks.o \ core/xpm_report.o \ - core/dsmm_developer.o \ validator/elf_code_segment_info.o \ - validator/exec_signature_info.o + validator/exec_signature_info.o \ + developer/dsmm_developer.o obj-$(CONFIG_SECURITY_XPM_DEBUG) += \ core/xpm_debugfs.o ccflags-$(CONFIG_SECURITY_XPM) += \ - -I$(srctree)/security/xpm/include \ + -I$(srctree)/security/xpm/core \ + -I$(srctree)/security/xpm/validator \ + -I$(srctree)/security/xpm/developer \ -I$(srctree)/security/selinux/include \ -I$(srctree)/security/selinux \ -I$(srctree)/fs \ + -I$(srctree)/fs/verity \ -I$(srctree)/fs/code_sign $(addprefix $(obj)/,$(obj-y)): $(obj)/flask.h diff --git a/xpm/core/xpm_common.c b/xpm/core/xpm_common.c new file mode 100644 index 0000000..9fcef36 --- /dev/null +++ b/xpm/core/xpm_common.c @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include "xpm_common.h" + +bool xpm_is_anonymous_vma(struct vm_area_struct *vma) +{ + return vma_is_anonymous(vma) || vma_is_shmem(vma); +} diff --git a/xpm/core/xpm_common.h b/xpm/core/xpm_common.h new file mode 100644 index 0000000..214401a --- /dev/null +++ b/xpm/core/xpm_common.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _XPM_COMMON_H +#define _XPM_COMMON_H + +#include +#include + +/** + * xpm_is_anonymous_vma - Determine whether vma is anonymous. + * + * @vma: Pointer to "struct vm_area_struct" which need to be determined. + * + * Returns true on anonymunt, 0 on permissive mode. + * + * NOTE: shemem also been treated as anonymous vma. + */ +bool xpm_is_anonymous_vma(struct vm_area_struct *vma); + +#endif /* _XPM_COMMON_H */ diff --git a/xpm/core/xpm_debugfs.c b/xpm/core/xpm_debugfs.c old mode 100755 new mode 100644 index 9265532..8b0cfc0 --- a/xpm/core/xpm_debugfs.c +++ b/xpm/core/xpm_debugfs.c @@ -4,19 +4,17 @@ */ #include -#include "xpm_log.h" -#include "xpm_hck.h" -#include "xpm_debugfs.h" -#define XPM_PERMISSIVE_MODE 0 -#define XPM_ENFORCE_MODE 1 +#include "xpm_debugfs.h" +#include "xpm_hck_hooks.h" +#include "xpm_log.h" static struct dentry *xpm_dir; static uint8_t xpm_mode = XPM_PERMISSIVE_MODE; -bool xpm_is_permissve_mode(void) +int xpm_ret(int ret) { - return xpm_mode == XPM_PERMISSIVE_MODE; + return xpm_mode == XPM_ENFORCE_MODE ? ret : 0; } int xpm_debugfs_init(void) diff --git a/xpm/include/xpm_debugfs.h b/xpm/core/xpm_debugfs.h old mode 100755 new mode 100644 similarity index 54% rename from xpm/include/xpm_debugfs.h rename to xpm/core/xpm_debugfs.h index 30575ba..50ddb12 --- a/xpm/include/xpm_debugfs.h +++ b/xpm/core/xpm_debugfs.h @@ -5,11 +5,21 @@ #ifndef _XPM_DEBUGFS_H +#define XPM_PERMISSIVE_MODE 0 +#define XPM_ENFORCE_MODE 1 + #ifdef CONFIG_SECURITY_XPM_DEBUG int xpm_debugfs_init(void); void xpm_debugfs_exit(void); -bool xpm_is_permissve_mode(void); +/** + * xpm_ret - Return value adapted to xpm enforce and permissive modes. + * + * @ret: Return value. + * + * Returns ret on enforce mode, 0 on permissive mode. + */ +int xpm_ret(int ret); #else static inline int xpm_debugfs_init(void) { @@ -20,9 +30,9 @@ static inline void xpm_debugfs_exit(void) { } -static inline bool xpm_is_permissve_mode(void) +static inline int xpm_ret(int ret) { - return true; + return XPM_PERMISSIVE_MODE; } #endif diff --git a/xpm/core/xpm_hck.c b/xpm/core/xpm_hck_hooks.c similarity index 40% rename from xpm/core/xpm_hck.c rename to xpm/core/xpm_hck_hooks.c index 5ee0be0..df45386 100644 --- a/xpm/core/xpm_hck.c +++ b/xpm/core/xpm_hck_hooks.c @@ -4,222 +4,22 @@ */ #include + +#include #include -#include +#include #include #include -#include #include -#include -#include -#include "avc.h" -#include "objsec.h" -#include "xpm_hck.h" + +#include "exec_signature_info.h" +#include "xpm_common.h" +#include "xpm_debugfs.h" +#include "xpm_hck_hooks.h" #include "xpm_log.h" #include "xpm_report.h" -#include "xpm_debugfs.h" -#include "exec_signature_info.h" - -static int xpm_value(int value) -{ - return xpm_is_permissve_mode() ? 0 : value; -} - -static bool xpm_is_anonymous_vma(struct vm_area_struct *vma) -{ - return vma_is_anonymous(vma) || vma_is_shmem(vma); -} - -static int xpm_avc_has_perm(u16 tclass, u32 requested) -{ - struct av_decision avd; - u32 sid = current_sid(); - int rc, rc2; - - rc = avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, - AVC_STRICT, &avd); - rc2 = avc_audit(&selinux_state, sid, sid, tclass, requested, &avd, rc, - NULL, AVC_STRICT); - if (rc2) - return rc2; - - return rc; -} - -static int xpm_validate_signature(struct vm_area_struct *vma, - struct exec_file_signature_info *info) -{ - unsigned long verified_data_end, vm_addr_end; - const struct inode *inode = (const struct inode *)info->inode; - - if (IS_ERR_OR_NULL(info)) - return xpm_avc_has_perm(SECCLASS_XPM, XPM__EXEC_NO_SIGN); - - if(!exec_file_signature_is_fs_verity(info)) - return 0; - - vm_addr_end = (vma->vm_pgoff << PAGE_SHIFT) - + (vma->vm_end - vma->vm_start); - verified_data_end = PAGE_ALIGN(fsverity_get_verified_data_size(inode)); - if (verified_data_end < vm_addr_end) { - xpm_log_error("data is out of verified data size."); - return -EPERM; - } - return 0; -} - -static int xpm_check_code_segment(bool is_exec, struct vm_area_struct *vma, - struct exec_file_signature_info *info) -{ - int i; - unsigned long vm_addr_start, vm_addr_end; - unsigned long seg_addr_start, seg_addr_end; - struct exec_segment_info *segments = info->code_segments; - - if (!is_exec) - return 0; - - if (!segments) { - xpm_log_error("code segments is NULL"); - return -EINVAL; - } - - vm_addr_start = vma->vm_pgoff << PAGE_SHIFT; - vm_addr_end = vm_addr_start + (vma->vm_end - vma->vm_start); - - for (i = 0; i < info->code_segment_count; i++) { - seg_addr_start = ALIGN_DOWN(segments[i].file_offset, PAGE_SIZE); - seg_addr_end = PAGE_ALIGN(segments[i].file_offset + - segments[i].size); - if ((vm_addr_start >= seg_addr_start) && - (vm_addr_end <= seg_addr_end)) - return 0; - } - - return xpm_avc_has_perm(SECCLASS_XPM, XPM__EXEC_NO_SIGN); -} - -static void xpm_check_signature_error(struct file *file, int err_num) -{ - char *full_path; - char *path; - - if (file == NULL) - return; - - path = __getname(); - if (path == NULL) { - xpm_log_error("malloc file name failed"); - return; - } - - full_path = file_path(file, path, PATH_MAX - 1); - if (IS_ERR(full_path)) { - xpm_log_error("get file d_path failed"); - return; - } - - xpm_log_error("xpm get %s signature info failed, errno = %d", full_path, -err_num); - __putname(path); - return; -} - -static int xpm_check_signature(struct vm_area_struct *vma, unsigned long prot) -{ - int ret; - bool is_exec; - struct exec_file_signature_info *info = NULL; - - /* vma is non-executable or mmap in xpm region just return */ - is_exec = !xpm_is_anonymous_vma(vma) && (prot & PROT_EXEC); - if (!((vma->vm_flags & VM_XPM) || is_exec)) - return 0; - - /* validate signature when vma is mmap in xpm region or executable */ - 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; - } - - ret = xpm_validate_signature(vma, info); - if (ret) { - xpm_log_error("xpm validate signature info failed"); - report_mmap_event(TYPE_SIGN_INVALID, vma, is_exec, prot); - goto exit; - } - - ret = xpm_check_code_segment(is_exec, vma, info); - if (ret) { - xpm_log_error("xpm check executable vma mmap code segment failed"); - report_mmap_event(TYPE_DATA_MMAP_CODE, vma, is_exec, prot); - goto exit; - } -exit: - put_exec_file_signature_info(info); - return ret; -} - -static int xpm_check_prot(struct vm_area_struct *vma, unsigned long prot) -{ - int ret; - 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; - } - - /* anonymous executable permission need controled by selinux */ - if (is_anon && (prot & PROT_EXEC)) { - ret = xpm_avc_has_perm(SECCLASS_XPM, XPM__EXEC_ANON_MEM); - if (ret) { - xpm_log_error("anonymous mmap not allow exec permission"); - report_mmap_event(TYPE_ANON_EXEC, vma, TYPE_ANON, prot); - return -EPERM; - } - } - - if (!is_anon && (prot & PROT_WRITE) && (prot & PROT_EXEC)) { - xpm_log_error("file mmap not allow write & exec permission"); - return -EPERM; - } - - return 0; -} - -static int xpm_common_check(struct vm_area_struct *vma, unsigned long prot) -{ - int ret; - - do { - ret = xpm_check_prot(vma, prot); - if (ret) - break; - - ret = xpm_check_signature(vma, prot); - } while (0); - - return xpm_value(ret); -} -static int xpm_mmap_check(struct vm_area_struct *vma) -{ - return xpm_common_check(vma, vma->vm_flags); -} - -static int xpm_mprotect_check(struct vm_area_struct *vma, - unsigned long reqprot, unsigned long prot) -{ - (void)reqprot; - - return xpm_common_check(vma, prot); -} - -void xpm_delete_cache_node(struct inode *file_node) +static void xpm_delete_cache_node(struct inode *file_node) { delete_exec_file_signature_info(file_node); } @@ -232,7 +32,10 @@ static void xpm_region_outer(unsigned long addr_start, unsigned long addr_end, if (!mm) return; - /* Already in xpm region, just return without judge */ + /* + * VM_UNMAPPED_AREA_XPM identifies the address to allocated in the + * xpm_region, just ignore. + */ if (flags & VM_UNMAPPED_AREA_XPM) return; @@ -281,15 +84,16 @@ void xpm_get_unmapped_area(unsigned long addr, unsigned long len, /* * A xpm readonly region is an area where any page mapped * will be marked with XPMReadonly. + * * Return 1 if a region is readonly, otherwise, return 0. */ static bool is_xpm_readonly_region(struct vm_area_struct *vma) { - /* 1. xpm region */ + /* xpm region */ if (vma->vm_flags & VM_XPM) return true; - /* 2. !anonymous && executable */ + /* !anonymous && executable */ if (!xpm_is_anonymous_vma(vma) && (vma->vm_flags & VM_EXEC)) return true; @@ -305,15 +109,15 @@ void xpm_integrity_check(struct vm_area_struct *vma, unsigned int vflags, /* integrity violation: write a readonly page */ if ((vflags & FAULT_FLAG_WRITE) && (vma->vm_flags & VM_WRITE) && PageXPMReadonly(page)) { - report_integrity_event(TYPE_INTEGRITY_RO, vma, page); - *ret = xpm_value(VM_FAULT_SIGSEGV); + report_integrity_event(INTEGRITY_RO, vma, page); + *ret = xpm_ret(VM_FAULT_SIGSEGV); return; } /* integrity violation: execute a writetained page */ if (PageXPMWritetainted(page) && is_xpm_readonly_region(vma)) { - report_integrity_event(TYPE_INTEGRITY_WT, vma, page); - *ret = xpm_value(VM_FAULT_SIGSEGV); + report_integrity_event(INTEGRITY_WT, vma, page); + *ret = xpm_ret(VM_FAULT_SIGSEGV); return; } } @@ -333,7 +137,7 @@ void xpm_integrity_update(struct vm_area_struct *vma, unsigned int vflags, SetPageXPMReadonly(page); } -void xpm_integrity_validate(struct vm_area_struct *vma, unsigned int vflags, +void xpm_integrity_validate(struct vm_area_struct *vma, unsigned int vflags, unsigned long addr, struct page *page, vm_fault_t *ret) { if (!page) @@ -345,8 +149,9 @@ void xpm_integrity_validate(struct vm_area_struct *vma, unsigned int vflags, } /* - * check the integrity of these two pages, return true if equal, - * otherwise false + * check the integrity of these two pages. + * + * Return true if equal, otherwise false. */ void xpm_integrity_equal(struct page *page, struct page *kpage, bool *ret) { @@ -357,16 +162,6 @@ void xpm_integrity_equal(struct page *page, struct page *kpage, bool *ret) (PageXPMReadonly(page) == PageXPMReadonly(kpage))); } -static struct security_hook_list xpm_hooks[] __lsm_ro_after_init = { - LSM_HOOK_INIT(mmap_region, xpm_mmap_check), - LSM_HOOK_INIT(file_mprotect, xpm_mprotect_check), -}; - -void xpm_register_xpm_hooks(void) -{ - security_add_hooks(xpm_hooks, ARRAY_SIZE(xpm_hooks), "xpm"); -} - void xpm_register_hck_hooks(void) { REGISTER_HCK_LITE_HOOK(xpm_delete_cache_node_lhck, diff --git a/xpm/include/xpm_hck.h b/xpm/core/xpm_hck_hooks.h similarity index 51% rename from xpm/include/xpm_hck.h rename to xpm/core/xpm_hck_hooks.h index 35cc279..225df0a 100644 --- a/xpm/include/xpm_hck.h +++ b/xpm/core/xpm_hck_hooks.h @@ -3,13 +3,9 @@ * Copyright (c) 2023 Huawei Device Co., Ltd. */ -#ifndef _XPM_HCK_H -#define _XPM_HCK_H - -void set_xpm_mode(uint8_t mode); - -void xpm_register_xpm_hooks(void); +#ifndef _XPM_HCK_HOOKS_H +#define _XPM_HCK_HOOKS_H void xpm_register_hck_hooks(void); -#endif /* _XPM_HCK_H */ +#endif /* _XPM_HCK_HOOKS_H */ diff --git a/xpm/include/xpm_log.h b/xpm/core/xpm_log.h similarity index 95% rename from xpm/include/xpm_log.h rename to xpm/core/xpm_log.h index 5638e75..0b45f65 100644 --- a/xpm/include/xpm_log.h +++ b/xpm/core/xpm_log.h @@ -6,8 +6,6 @@ #ifndef _XPM_LOG_H #define _XPM_LOG_H -#define XPM_CHECK_FAILED (-1024) - #define XPM_TAG "xpm_kernel" #define XPM_INFO_TAG "I" #define XPM_ERROR_TAG "E" diff --git a/xpm/core/xpm_misc.c b/xpm/core/xpm_misc_device.c old mode 100755 new mode 100644 similarity index 50% rename from xpm/core/xpm_misc.c rename to xpm/core/xpm_misc_device.c index 3879628..b289375 --- a/xpm/core/xpm_misc.c +++ b/xpm/core/xpm_misc_device.c @@ -3,64 +3,103 @@ * Copyright (c) 2023 Huawei Device Co., Ltd. */ -#include "xpm_misc.h" - +#include +#include +#include +#include #include #include -#include -#include #include -#include -#include + +#include "code_sign_ext.h" #include "xpm_log.h" +#include "xpm_misc_device.h" #include "xpm_report.h" -#define XPM_SET_REGION _IOW('x', 0x01, struct xpm_region_info) +#define XPM_SET_REGION _IOW('x', 0x01, struct xpm_config) +#define XPM_SET_OWNERID _IOW('x', 0x02, struct xpm_config) -static int xpm_set_region(unsigned long addr_base, unsigned long length) +static int xpm_set_region(struct xpm_config *config) { - int ret = 0; - unsigned long addr; + uint64_t addr; struct mm_struct *mm = current->mm; if (!mm) return -EINVAL; - if (mmap_write_lock_killable(mm)) - return -EINTR; - if ((mm->xpm_region.addr_start != 0) || (mm->xpm_region.addr_end != 0)) { xpm_log_info("xpm region has been set"); - goto exit; + return 0; } - addr = get_unmapped_area(NULL, addr_base, length, 0, 0); - if (IS_ERR_VALUE(addr) || (ULONG_MAX - addr_base < length)) { + addr = get_unmapped_area(NULL, config->region_addr, + config->region_length, 0, 0); + if (IS_ERR_VALUE(addr) || (ULLONG_MAX - addr < config->region_length)) { xpm_log_error("xpm get unmmaped area failed"); - ret = -EINVAL; - goto exit; + return -EINVAL; } + if (mmap_write_lock_killable(mm)) + return -EINTR; + mm->xpm_region.addr_start = addr; - mm->xpm_region.addr_end = addr + length; -exit: + mm->xpm_region.addr_end = addr + config->region_length; mmap_write_unlock(mm); - return ret; + + return 0; +} + +static int xpm_set_ownerid(struct xpm_config *config) +{ + struct mm_struct *mm = current->mm; + + if (!mm) + return -EINVAL; + + if (config->id_type >= PROCESS_OWNERID_MAX) { + xpm_log_error("input ownerid type is invalid"); + return -EINVAL; + } + +#ifndef CONFIG_SECURITY_XPM_DEBUG + if ((mm->pcs_info.id_type == PROCESS_OWNERID_APP) || + mm->pcs_info.id_type == PROCESS_OWNERID_DEBUG) { + xpm_log_info("process ownerid has been set"); + return 0; + } +#endif + + if (config->ownerid[MAX_OWNERID_LEN - 1] != '\0') { + xpm_log_error("input ownerid string is invalid"); + return -EINVAL; + } + + if (mmap_write_lock_killable(mm)) + return -EINTR; + + code_sign_set_ownerid(&mm->pcs_info, config->id_type, + config->ownerid, strlen(config->ownerid)); + mmap_write_unlock(mm); + + return 0; } static long xpm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int ret; - struct xpm_region_info info = {0}; + struct xpm_config config = {0}; - if (unlikely(copy_from_user(&info, (void __user *)(uintptr_t)arg, - sizeof(struct xpm_region_info)))) + if (unlikely(copy_from_user(&config, u64_to_user_ptr((uint64_t)arg), + sizeof(struct xpm_config)))) return -EFAULT; switch (cmd) { case XPM_SET_REGION: - ret = xpm_set_region(info.addr_base, info.length); + ret = xpm_set_region(&config); + break; + case XPM_SET_OWNERID: + ret = xpm_set_ownerid(&config); break; default: xpm_log_error("xpm ioctl cmd error, cmd = %d", cmd); @@ -71,14 +110,6 @@ static long xpm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return ret; } -#ifdef CONFIG_COMPAT -static long xpm_compat_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return 0; -} -#endif - static int xpm_open(struct inode *inode, struct file *file) { return 0; @@ -95,7 +126,7 @@ static const struct file_operations xpm_fops = { .release = xpm_release, .unlocked_ioctl = xpm_ioctl, #ifdef CONFIG_COMPAT - .compat_ioctl = xpm_compat_ioctl, + .compat_ioctl = xpm_ioctl, #endif }; diff --git a/xpm/include/xpm_misc.h b/xpm/core/xpm_misc_device.h old mode 100755 new mode 100644 similarity index 41% rename from xpm/include/xpm_misc.h rename to xpm/core/xpm_misc_device.h index 9b459a0..e7a4366 --- a/xpm/include/xpm_misc.h +++ b/xpm/core/xpm_misc_device.h @@ -3,17 +3,22 @@ * Copyright (c) 2023 Huawei Device Co., Ltd. */ -#ifndef _XPM_MISC_H -#define _XPM_MISC_H +#ifndef _XPM_MISC_DEVICE_H +#define _XPM_MISC_DEVICE_H -#include +#include -struct xpm_region_info { - uint64_t addr_base; - uint64_t length; +#define MAX_OWNERID_LEN 64 + +struct xpm_config { + uint64_t region_addr; + uint64_t region_length; + + uint32_t id_type; + char ownerid[MAX_OWNERID_LEN]; }; int xpm_register_misc_device(void); void xpm_deregister_misc_device(void); -#endif /* _XPM_MISC_H */ +#endif /* _XPM_MISC_DEVICE_H */ diff --git a/xpm/core/xpm_module.c b/xpm/core/xpm_module.c old mode 100755 new mode 100644 index d2fcb50..c86b1bd --- a/xpm/core/xpm_module.c +++ b/xpm/core/xpm_module.c @@ -7,12 +7,14 @@ #include #include #include -#include "xpm_log.h" -#include "xpm_hck.h" -#include "xpm_misc.h" -#include "xpm_report.h" -#include "xpm_debugfs.h" + #include "dsmm_developer.h" +#include "xpm_debugfs.h" +#include "xpm_hck_hooks.h" +#include "xpm_misc_device.h" +#include "xpm_security_hooks.h" +#include "xpm_report.h" +#include "xpm_log.h" static int __init xpm_module_init(void) { @@ -21,7 +23,7 @@ static int __init xpm_module_init(void) ret = xpm_register_misc_device(); if (ret) { xpm_log_error("xpm register misc device failed, ret = %d", ret); - report_init_event(TYPE_DEVICEFS_UNINIT); + report_init_event(DEVICEFS_UNINIT); return ret; } @@ -29,11 +31,11 @@ static int __init xpm_module_init(void) if (ret) { xpm_log_error("xpm init debugfs failed, ret = %d", ret); xpm_deregister_misc_device(); - report_init_event(TYPE_DEBUGFS_UNINIT); + report_init_event(DEBUGFS_UNINIT); return ret; } - xpm_register_xpm_hooks(); + xpm_register_security_hooks(); xpm_register_hck_hooks(); dsmm_developer_proc_create(); diff --git a/xpm/core/xpm_report.c b/xpm/core/xpm_report.c index 202f9f9..a674930 100644 --- a/xpm/core/xpm_report.c +++ b/xpm/core/xpm_report.c @@ -3,18 +3,30 @@ * Copyright (c) 2023 Huawei Device Co., Ltd. */ +#include +#include +#include #include -#include #include -#include +#include #include -#include + #ifdef CONFIG_HW_KERNEL_SG #include #endif + +#include "code_sign_ext.h" +#include "fsverity_private.h" #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; @@ -22,43 +34,51 @@ typedef struct { unsigned int content_len; char content[0]; } event_info; +#endif -unsigned int report_security_info(const event_info *event) +unsigned int xpm_report_security_info(const event_info *event) { - xpm_log_info("%d: %s", event->event_id, event->content); + xpm_log_error("%d: %s", event->event_id, event->content); + +#ifdef CONFIG_HW_KERNEL_SG + return report_security_info(event); +#else return 0; -} #endif +} -static char *xpm_get_filename(struct xpm_event_param *param, char *buf, int len) +static void xpm_set_filename(struct file *file, struct xpm_report_info *info) { char *filename = NULL; - struct file *file = NULL; + char *buffer = NULL; - if (param->file) - file = param->file; - else if (param->vma && param->vma->vm_file) - file = param->vma->vm_file; - else - return NULL; + if (!file) + return; - filename = d_absolute_path(&file->f_path, buf, len); + buffer = kzalloc(sizeof(info->filename), GFP_ATOMIC); + if (!buffer) { + xpm_log_error("alloc filename buffer failed"); + return; + } + + filename = file_path(file, buffer, sizeof(info->filename) - 1); if (IS_ERR(filename)) { - xpm_log_error("xpm get absolute path failed"); - return NULL; + xpm_log_error("xpm set file path failed"); + } else { + strcpy(info->filename, filename); } - return filename; + kfree(buffer); } -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 +88,24 @@ 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) { - 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(vm_prot, %lu)"," + JVAL_PAIR(vm_pgoff, %lu)", "JVAL_PAIR(vm_size, %lu)", " + JVAL_PAIR(p_id_type, %u)", "JSTR_PAIR(p_ownerid, %u)", " + JVAL_PAIR(f_id_type, %u)", "JSTR_PAIR(f_ownerid, %u)", " + JSTR_PAIR(timestamp, %llu)" }", + info->event_type, info->code_type, info->pid, info->comm, + info->filename, info->vm_prot, info->vm_pgoff, info->vm_size, + info->pcs_info.id_type, info->pcs_info.ownerid, + info->fcs_info.id_type, info->fcs_info.ownerid, + info->timestamp); if (len < 0 || len > content_len) { xpm_log_error("snprintf code mmap content failed"); @@ -103,16 +115,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(timestap, %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 +135,19 @@ 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; - - if (!param->vma || !param->page) { - xpm_log_error("input vma or page is NULL"); - return -EINVAL; - } - - page_type = PageKsm(param->page) ? - "[ksm]" : PageAnon(param->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(vm_pgprot, %lu)", "JVAL_PAIR(timestamp, %llu)" }", + info->event_type, info->pid, info->comm, info->filename, + info->page_type, info->page_index, info->vm_pgprot, + info->timestamp); if (len < 0 || len > content_len) { xpm_log_error("snprintf init integrity failed"); @@ -153,120 +157,152 @@ 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 }, - [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 }, -}; - -static int report_event_inner(enum xpm_event_type type, - struct xpm_event_param *param, event_info *event) +static void xpm_set_report_info(struct xpm_report_param *param, + struct xpm_report_info *info) { - int ret; + struct fsverity_info *vi = NULL; + struct file *file = param->file; + struct mm_struct *mm = current->mm; + + info->event_type = param->event_type; + info->code_type = code_type_tbl[param->code_type]; - ret = xpm_event[type].set_content(param, event->content, - MAX_CONTENT_LEN); - if (ret) { - xpm_log_error("type [%d] set content failed", type); - return ret; + info->pid = current->pid; + memcpy(info->comm, current->comm, TASK_COMM_LEN); + + if (mm) { + info->pcs_info.id_type = mm->pcs_info.id_type; + info->pcs_info.ownerid = mm->pcs_info.ownerid; } - event->content_len = strlen(event->content); - event->event_id = xpm_event[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); - return ret; + + info->vm_prot = param->vm_prot & PROT_MASK; + if (param->vma) { + info->vm_pgoff = param->vma->vm_pgoff; + info->vm_size = param->vma->vm_end - param->vma->vm_start; + info->vm_pgprot = param->vma->vm_page_prot.pgprot & PROT_MASK; + file = param->vma->vm_file; } - return 0; + if (param->page) { + info->page_type = PageKsm(param->page) ? + "[ksm]" : PageAnon(param->page) ? "[anon]" : "[file]"; + info->page_index = param->page->index; + } + + /* init file ownerid type SYSTEM */ + info->fcs_info.id_type = FILE_OWNERID_SYSTEM; + if (file) { + xpm_set_filename(file, info); + vi = fsverity_get_info(file_inode(file)); + if (vi) { + info->fcs_info.id_type = vi->fcs_info.id_type; + info->fcs_info.ownerid = vi->fcs_info.ownerid; + } + } + + info->timestamp = ktime_get_real_seconds(); } -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 *event = NULL; + struct xpm_report_info *info = NULL; - if (!(xpm_event[type].set_content)) { - xpm_log_error("type [%d] set content func invalid", type); + if (!param->event_type) { + xpm_log_error("xpm event type is NULL"); return -EINVAL; } - sg_event = kzalloc(sizeof(event_info) + MAX_CONTENT_LEN, GFP_KERNEL); - if (!sg_event) { - xpm_log_error("alloc security guard event failed"); + info = kzalloc(sizeof(struct xpm_report_info), GFP_ATOMIC); + if (!info) { + xpm_log_error("alloc xpm report info struct failed"); return -ENOMEM; } - buf = __getname(); - if (!buf) { - xpm_log_error("alloc file name buf failed"); - kfree(sg_event); + event = kzalloc(sizeof(event_info) + MAX_CONTENT_LEN, GFP_ATOMIC); + if (!event) { + xpm_log_error("alloc security guard event failed"); + kfree(info); 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); - kfree(sg_event); + do { + event->version = XPM_EVENT_VERSION; + event->event_id = param->event_id; + + /* set xpm report info from param */ + xpm_set_report_info(param, info); + ret = param->set_content(info, event->content, MAX_CONTENT_LEN); + if (ret) { + xpm_log_error("type [%s] set content failed", + param->event_type); + break; + } + event->content_len = strlen(event->content); + + ret = xpm_report_security_info(event); + if (ret) { + xpm_log_error("type [%s] report security info failed", + param->event_type); + break; + } + + } while (0); + + kfree(info); + kfree(event); return ret; } -void report_init_event(enum xpm_event_type type) +void report_init_event(char *event_type) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = {0}; + + param.event_type = event_type; + param.event_id = EVENT_INIT; + param.set_content = &set_init_content; - 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) +void report_file_event(char *event_type, struct file *file) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = {0}; + param.event_type = event_type; + param.event_id = EVENT_FILE; param.file = file; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + param.set_content = &set_file_content; + + 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) +void report_mmap_event(char *event_type, enum xpm_code_type code_type, + struct vm_area_struct *vma, unsigned long vm_prot) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = {0}; + param.event_type = event_type; + param.event_id = EVENT_MMAP; + param.code_type = code_type; param.vma = vma; - param.code = code; - param.prot = prot; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + param.vm_prot = vm_prot; + param.set_content = &set_mmap_content; + + xpm_report_ratelimited(xpm_report_event, ¶m); } -void report_integrity_event(enum xpm_event_type type, - struct vm_area_struct *vma, struct page *page) +void report_integrity_event(char *event_type, struct vm_area_struct *vma, + struct page *page) { - struct xpm_event_param param = {0}; + struct xpm_report_param param = {0}; + param.event_type = event_type; + param.event_id = EVENT_INTEGRITY; param.vma = vma; param.page = page; - xpm_report_ratelimited(xpm_report_event, type, ¶m); + param.set_content = &set_integrity_content; + + xpm_report_ratelimited(xpm_report_event, ¶m); } diff --git a/xpm/include/xpm_report.h b/xpm/core/xpm_report.h similarity index 42% rename from xpm/include/xpm_report.h rename to xpm/core/xpm_report.h index aff1f67..e6c4516 100644 --- a/xpm/include/xpm_report.h +++ b/xpm/core/xpm_report.h @@ -8,6 +8,36 @@ #include #include +#include + +#define NULL_STR "NULL" + +#define MAX_FILENAME_LEN 128 + +/* EVENT_INIT */ +#define DEVICEFS_UNINIT "devicefs uninitialized" +#define DEBUGFS_UNINIT "debugfs uninitialized" +#define DM_DISABLE "dm-verity disable" + +/* EVENT_FILE */ +#define FORMAT_UNDEF "unkown file format" + +/* EVENT_MMAP */ +#define ANON_EXEC "anon executed" +#define GET_SIGN_FAIL "get signature info failed" +#define SIGN_INVALID "invalid signature" +#define DATA_MMAP_CODE "data mmap code" +#define OWNERID_INCONSISTENT "ownerid inconsistent" + +/* EVENT_INTEGRITY */ +#define INTEGRITY_RO "code tampered" +#define INTEGRITY_WT "data executed" + +enum xpm_code_type { + TYPE_ABC = 0, + TYPE_ELF, + TYPE_ANON, +}; enum xpm_event_id { EVENT_INIT = 1011009110, @@ -16,41 +46,39 @@ enum xpm_event_id { EVENT_INTEGRITY = 1011009113, }; -enum xpm_event_type { - TYPE_DEVICEFS_UNINIT = 0, - TYPE_DEBUGFS_UNINIT, - TYPE_DM_DISABLE, - TYPE_FORMAT_UNDEF, - TYPE_ANON_EXEC, - TYPE_SIGN_INVALID, - TYPE_DATA_MMAP_CODE, - TYPE_INTEGRITY_RO, - TYPE_INTEGRITY_WT, -}; +/* set of report info */ +struct xpm_report_info { + char *event_type; + char *code_type; -enum { - TYPE_ABC, - TYPE_ELF, - TYPE_ANON, -}; + pid_t pid; + char comm[TASK_COMM_LEN]; + char filename[MAX_FILENAME_LEN + 1]; + struct cs_info pcs_info; + struct cs_info fcs_info; + + unsigned long vm_prot; + unsigned long vm_pgprot; + unsigned long vm_pgoff; + unsigned long vm_size; + + char *page_type; + pgoff_t page_index; -struct xpm_event_param { - char *event_type; - char *filename; ktime_t timestamp; - pid_t pid; +}; +/* set of caller parameters */ +struct xpm_report_param { + char *event_type; + enum xpm_event_id event_id; + enum xpm_code_type code_type; struct vm_area_struct *vma; + unsigned long vm_prot; struct page *page; struct file *file; - int code; - unsigned long prot; -}; -struct xpm_event_info { - char *event_type; - enum xpm_event_id event_id; - int (*set_content)(struct xpm_event_param *param, uint8_t *content, + int (*set_content)(struct xpm_report_info *info, uint8_t *content, uint32_t content_len); }; @@ -58,7 +86,6 @@ struct xpm_event_info { #define XPM_EVENT_VERSION 0 #ifndef CONFIG_SECURITY_XPM_DEBUG - #define xpm_report_ratelimited(func, fmt, ...) \ do { \ static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL, \ @@ -76,11 +103,11 @@ struct xpm_event_info { #define JVAL_PAIR(val, format) JSTR(val) ": " #format #define JSTR_PAIR(val, format) JSTR(val) ": " JSTR(format) -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); -void report_integrity_event(enum xpm_event_type type, - struct vm_area_struct *vma, struct page *page); +void report_init_event(char *event_type); +void report_file_event(char *event_type, struct file *file); +void report_mmap_event(char *event_type, enum xpm_code_type code_type, + struct vm_area_struct *vma, unsigned long prot); +void report_integrity_event(char *event_type, struct vm_area_struct *vma, + struct page *page); #endif /* _XPM_REPORT_H */ diff --git a/xpm/core/xpm_security_hooks.c b/xpm/core/xpm_security_hooks.c new file mode 100644 index 0000000..5fe5b37 --- /dev/null +++ b/xpm/core/xpm_security_hooks.c @@ -0,0 +1,373 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include + +#include "avc.h" +#include "objsec.h" +#include "exec_signature_info.h" +#include "fsverity_private.h" +#include "code_sign_ext.h" +#include "xpm_common.h" +#include "xpm_debugfs.h" +#include "xpm_log.h" +#include "xpm_report.h" +#include "xpm_security_hooks.h" + +enum ownerid_policy_type { + DENY = 0, + ALLOW, + CHECK, +}; + +static uint32_t ownerid_policy[PROCESS_OWNERID_MAX][FILE_OWNERID_MAX] __ro_after_init; + +static void init_ownerid_policy(void) +{ + ownerid_policy[PROCESS_OWNERID_SYSTEM][FILE_OWNERID_SYSTEM] = ALLOW; + + ownerid_policy[PROCESS_OWNERID_APP][FILE_OWNERID_SYSTEM] = ALLOW; + ownerid_policy[PROCESS_OWNERID_APP][FILE_OWNERID_SHARED] = ALLOW; + ownerid_policy[PROCESS_OWNERID_APP][FILE_OWNERID_APP] = CHECK; + + ownerid_policy[PROCESS_OWNERID_DEBUG][FILE_OWNERID_SYSTEM] = ALLOW; + ownerid_policy[PROCESS_OWNERID_DEBUG][FILE_OWNERID_SHARED] = ALLOW; + ownerid_policy[PROCESS_OWNERID_DEBUG][FILE_OWNERID_DEBUG] = ALLOW; + + ownerid_policy[PROCESS_OWNERID_COMPAT][FILE_OWNERID_SYSTEM] = ALLOW; + ownerid_policy[PROCESS_OWNERID_COMPAT][FILE_OWNERID_COMPAT] = ALLOW; + + for (int i = 0; i < FILE_OWNERID_MAX; i++) { + ownerid_policy[PROCESS_OWNERID_EXTEND][i] = ALLOW; + } +} + +static int check_same_ownerid(struct cs_info *pcs_info, struct cs_info *fcs_info) +{ + if ((pcs_info->id_type == fcs_info->id_type) && + (pcs_info->ownerid == fcs_info->ownerid)) { + return 0; + } + + return -EPERM; +} + +int xpm_check_ownerid_policy(struct cs_info *pcs_info, struct cs_info *fcs_info) +{ + uint32_t type; + + if (!pcs_info || !fcs_info) { + xpm_log_error("input pcs_info or fcs_info is NULL"); + return -EINVAL; + } + + if ((pcs_info->id_type >= PROCESS_OWNERID_MAX) || + (fcs_info->id_type >= FILE_OWNERID_MAX)) { + xpm_log_info("process or file ownerid exceed maximum value"); + return -EINVAL; + } + + type = ownerid_policy[pcs_info->id_type][fcs_info->id_type]; + switch (type) { + case DENY: + return -EPERM; + case ALLOW: + return 0; + case CHECK: + return check_same_ownerid(pcs_info, fcs_info); + default: + xpm_log_error("input ownerid type is invalid: %u", type); + break; + } + + return -EINVAL; +} + +static int xpm_get_file_cs_info(struct cs_info *fcs_info, + struct exec_file_signature_info *info) +{ + /* exec file is dm-verity */ + if (exec_file_signature_is_dm_verity(info)) { + code_sign_set_ownerid(fcs_info, FILE_OWNERID_SYSTEM, NULL, 0); + return 0; + } + + /* exec file is fs-verity */ + if (exec_file_signature_is_fs_verity(info)) { + struct fsverity_info *vi = fsverity_get_info(info->inode); + if (!vi) { + xpm_log_error("get verity info failed in fs-verity"); + return -EINVAL; + } + + fcs_info->id_type = vi->fcs_info.id_type; + fcs_info->ownerid = vi->fcs_info.ownerid; + return 0; + } + + xpm_log_error("invalid code signature info type"); + return -EINVAL; +} + +int xpm_get_process_cs_info(struct cs_info *pcs_info) +{ + int ret; + struct exec_file_signature_info *info = NULL; + struct file *exe_file = NULL; + struct cs_info fcs_info = {0}; + struct mm_struct *mm = current->mm; + + if (!mm) + return -EINVAL; + + /* process cs_info has not been init, just init from exe file */ + if (mm->pcs_info.id_type == PROCESS_OWNERID_UNINIT) { + exe_file = get_task_exe_file(current); + if (!exe_file) { + xpm_log_error("xpm get exe_file failed"); + return -ENOEXEC; + } + + ret = get_exec_file_signature_info(exe_file, true, &info); + /* reduce exe_file reference count */ + fput(exe_file); + if (ret || (info == NULL)) { + xpm_log_error("xpm get exe_file signature info failed"); + return ret; + } + + ret = xpm_get_file_cs_info(&fcs_info, info); + if (ret) { + xpm_log_error("xpm get exe_file cs info failed"); + return ret; + } + + /* process's ownerid is correspond to file */ + mm->pcs_info.id_type = fcs_info.id_type; + mm->pcs_info.ownerid = fcs_info.ownerid; + } + pcs_info->id_type = mm->pcs_info.id_type; + pcs_info->ownerid = mm->pcs_info.ownerid; + + return 0; +} + +static int xpm_check_ownerid(struct vm_area_struct *vma, + struct exec_file_signature_info *info) +{ + int ret; + struct cs_info pcs_info = {0}; + struct cs_info fcs_info = {0}; + + ret = xpm_get_process_cs_info(&pcs_info); + if (ret) { + xpm_log_error("xpm get process cs_info falied"); + return ret; + } + + ret = xpm_get_file_cs_info(&fcs_info, info); + if (ret) { + xpm_log_error("xpm get file cs_info falied"); + return ret; + } + + return xpm_check_ownerid_policy(&pcs_info, &fcs_info); +} + +static int xpm_avc_has_perm(u16 tclass, u32 requested) +{ + struct av_decision avd; + u32 sid = current_sid(); + + return avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, + AVC_STRICT, &avd); +} + +static int xpm_validate_signature(struct vm_area_struct *vma, + struct exec_file_signature_info *info) +{ + unsigned long verified_data_end, vm_addr_end; + const struct inode *inode = (const struct inode *)info->inode; + + if (IS_ERR_OR_NULL(info)) { + xpm_log_error("signature info is NULL"); + return -EPERM; + } + + if(!exec_file_signature_is_fs_verity(info)) + return 0; + + vm_addr_end = (vma->vm_pgoff << PAGE_SHIFT) + + (vma->vm_end - vma->vm_start); + verified_data_end = PAGE_ALIGN(fsverity_get_verified_data_size(inode)); + if (verified_data_end < vm_addr_end) { + xpm_log_error("data is out of verified data size"); + return -EPERM; + } + + return 0; +} + +static int xpm_check_code_segment(bool is_exec, struct vm_area_struct *vma, + struct exec_file_signature_info *info) +{ + int i; + unsigned long vm_addr_start, vm_addr_end; + unsigned long seg_addr_start, seg_addr_end; + struct exec_segment_info *segments = info->code_segments; + + if (!is_exec) + return 0; + + if (!segments) { + xpm_log_error("code segments is NULL"); + return -EINVAL; + } + + vm_addr_start = vma->vm_pgoff << PAGE_SHIFT; + vm_addr_end = vm_addr_start + (vma->vm_end - vma->vm_start); + + for (i = 0; i < info->code_segment_count; i++) { + seg_addr_start = ALIGN_DOWN(segments[i].file_offset, PAGE_SIZE); + seg_addr_end = PAGE_ALIGN(segments[i].file_offset + + segments[i].size); + if ((vm_addr_start >= seg_addr_start) && + (vm_addr_end <= seg_addr_end)) + return 0; + } + + return -EPERM; +} + +static int xpm_check_signature(struct vm_area_struct *vma, unsigned long prot) +{ + int ret; + bool is_exec; + struct exec_file_signature_info *info = NULL; + + /* vma is non-executable or mmap in xpm region just return */ + is_exec = !xpm_is_anonymous_vma(vma) && (prot & PROT_EXEC); + if (!((vma->vm_flags & VM_XPM) || is_exec)) + return 0; + + /* process has exec_no_sign permission just return */ + if (xpm_avc_has_perm(SECCLASS_XPM, XPM__EXEC_NO_SIGN) == 0) + return 0; + + /* validate signature when vma is mmap in xpm region or executable */ + ret = get_exec_file_signature_info(vma->vm_file, is_exec, &info); + if (ret) { + report_mmap_event(GET_SIGN_FAIL, is_exec ? TYPE_ELF : TYPE_ABC, + vma, prot); + return ret; + } + + do { + ret = xpm_validate_signature(vma, info); + if (ret) { + report_mmap_event(SIGN_INVALID, + is_exec ? TYPE_ELF : TYPE_ABC, vma, prot); + break; + } + + ret = xpm_check_code_segment(is_exec, vma, info); + if (ret) { + report_mmap_event(DATA_MMAP_CODE, + is_exec ? TYPE_ELF : TYPE_ABC, vma, prot); + break; + } + + ret = xpm_check_ownerid(vma, info); + if (ret) { + report_mmap_event(OWNERID_INCONSISTENT, + is_exec ? TYPE_ELF : TYPE_ABC, vma, prot); + break; + } + } while (0); + + if (info) + put_exec_file_signature_info(info); + + return ret; +} + +static int xpm_check_prot(struct vm_area_struct *vma, unsigned long prot) +{ + int ret; + bool is_anon; + + is_anon = xpm_is_anonymous_vma(vma); + + /* check for xpm region vma prot */ + 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; + } + + /* check for anonymous vma prot, anonymous executable permission need + * controled by selinux + */ + if (is_anon && (prot & PROT_EXEC)) { + ret = xpm_avc_has_perm(SECCLASS_XPM, XPM__EXEC_ANON_MEM); + if (ret) { + report_mmap_event(ANON_EXEC, TYPE_ANON, vma, prot); + return -EPERM; + } + + return 0; + } + + /* check for non-anonymous vma prot */ + if (!is_anon && (prot & PROT_WRITE) && (prot & PROT_EXEC)) { + xpm_log_error("file mmap not allow write & exec permission"); + return -EPERM; + } + + return 0; +} + +static int xpm_common_check(struct vm_area_struct *vma, unsigned long prot) +{ + int ret; + + do { + ret = xpm_check_prot(vma, prot); + if (ret) + break; + + ret = xpm_check_signature(vma, prot); + } while (0); + + return xpm_ret(ret); +} + +static int xpm_mmap_check(struct vm_area_struct *vma) +{ + return xpm_common_check(vma, vma->vm_flags); +} + +static int xpm_mprotect_check(struct vm_area_struct *vma, + unsigned long reqprot, unsigned long prot) +{ + (void)reqprot; + + return xpm_common_check(vma, prot); +} + +static struct security_hook_list xpm_hooks[] __lsm_ro_after_init = { + LSM_HOOK_INIT(mmap_region, xpm_mmap_check), + LSM_HOOK_INIT(file_mprotect, xpm_mprotect_check), +}; + +void xpm_register_security_hooks(void) +{ + init_ownerid_policy(); + security_add_hooks(xpm_hooks, ARRAY_SIZE(xpm_hooks), "xpm"); +} diff --git a/xpm/core/xpm_security_hooks.h b/xpm/core/xpm_security_hooks.h new file mode 100644 index 0000000..e95553c --- /dev/null +++ b/xpm/core/xpm_security_hooks.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _XPM_SECURITY_HOOKS_H +#define _XPM_SECURITY_HOOKS_H + +void xpm_register_security_hooks(void); + +#endif /* _XPM_SECURITY_HOOKS_H */ diff --git a/xpm/core/dsmm_developer.c b/xpm/developer/dsmm_developer.c similarity index 76% rename from xpm/core/dsmm_developer.c rename to xpm/developer/dsmm_developer.c index 66b10f8..00b0b77 100644 --- a/xpm/core/dsmm_developer.c +++ b/xpm/developer/dsmm_developer.c @@ -4,6 +4,7 @@ */ #include + #include "dsmm_developer.h" #include "xpm_log.h" @@ -12,20 +13,21 @@ #define DSMM_DEVELOPER_PARAM_NAME "const.security.developermode.state" static struct proc_dir_entry *g_dsmm_dir; +static uint32_t developer_state = STATE_UNINT; -static const char *g_developer_status[BUILD_VARIANT_MAX][DEVELOPER_PROC_STATUS_MAX] = { - { DEVELOPER_STATUS_OFF, DEVELOPER_STATUS_ON, DEVELOPER_STATUS_OFF }, - { DEVELOPER_STATUS_ON, DEVELOPER_STATUS_ON, DEVELOPER_STATUS_OFF }, +static uint32_t g_state_table[BUILD_VARIANT_MAX][CMDLINE_DEV_STATE_MAX] = { + { STATE_OFF, STATE_ON, STATE_OFF }, + { STATE_ON, STATE_ON, STATE_ON }, }; static int get_developer_status(uint32_t *status) { if (!strstr(saved_command_line, "developer_mode=")) { - *status = DEVELOPER_PROC_STATUS_NA; + *status = CMDLINE_DEV_STATE_NA; } else if (strstr(saved_command_line, "developer_mode=1")) { - *status = DEVELOPER_PROC_STATUS_ON; + *status = CMDLINE_DEV_STATE_ON; } else if (strstr(saved_command_line, "developer_mode=0")) { - *status = DEVELOPER_PROC_STATUS_OFF; + *status = CMDLINE_DEV_STATE_OFF; } else { xpm_log_error("invalid developer_mode value in cmdline"); return -EINVAL; @@ -48,20 +50,25 @@ static int get_build_variant(uint32_t *variant) return 0; } -const char *developer_mode_state(void) +int get_developer_mode_state(void) { uint32_t variant, status; + if (developer_state != STATE_UNINT) + return developer_state; + #ifdef CONFIG_DSMM_DEVELOPER_ENABLE if (get_build_variant(&variant) || get_developer_status(&status)) { xpm_log_error("get build variant or developer status failed"); - return NULL; + developer_state = STATE_OFF; + } else { + developer_state = g_state_table[variant][status]; } - - return g_developer_status[variant][status]; #else - return DEVELOPER_STATUS_ON; + developer_state = STATE_ON; #endif + + return developer_state; } #define PROC_DEVELOPER_LEN 50 @@ -69,16 +76,13 @@ static ssize_t dsmm_read_developer_proc(struct file *file, char __user *buf, size_t count, loff_t *pos) { size_t len; + uint32_t state; char proc_developer[PROC_DEVELOPER_LEN] = {0}; - const char *developer_state = developer_mode_state(); - - if (!developer_state) { - xpm_log_error("developer mode state invalid"); - return 0; - } + state = get_developer_mode_state(); len = snprintf(proc_developer, PROC_DEVELOPER_LEN - 1, - DSMM_DEVELOPER_PARAM_NAME"=%s", developer_state); + DSMM_DEVELOPER_PARAM_NAME"=%s", + state == STATE_ON ? "true" : "false"); return simple_read_from_buffer(buf, count, pos, proc_developer, len); } diff --git a/xpm/include/dsmm_developer.h b/xpm/developer/dsmm_developer.h similarity index 36% rename from xpm/include/dsmm_developer.h rename to xpm/developer/dsmm_developer.h index 5f19bec..36d5c04 100644 --- a/xpm/include/dsmm_developer.h +++ b/xpm/developer/dsmm_developer.h @@ -3,29 +3,38 @@ * Copyright (c) 2023 Huawei Device Co., Ltd. */ -#ifndef DSMM_DEVELOPER_H -#define DSMM_DEVELOPER_H +#ifndef _DSMM_DEVELOPER_H +#define _DSMM_DEVELOPER_H -#define DEVELOPER_STATUS_ON "true" -#define DEVELOPER_STATUS_OFF "false" +#define STATE_UNINT 0 +#define STATE_ON 1 +#define STATE_OFF 2 enum build_variant { BUILD_VARIANT_USER = 0, BUILD_VARIANT_ENG, + BUILD_VARIANT_MAX, }; -enum developer_proc_status { - DEVELOPER_PROC_STATUS_NA = 0, - DEVELOPER_PROC_STATUS_ON, - DEVELOPER_PROC_STATUS_OFF, - DEVELOPER_PROC_STATUS_MAX, -}; +enum cmdline_dev_state { + CMDLINE_DEV_STATE_NA = 0, + CMDLINE_DEV_STATE_ON, + CMDLINE_DEV_STATE_OFF, -const char *developer_mode_state(void); + CMDLINE_DEV_STATE_MAX, +}; void dsmm_developer_proc_create(void); - void dsmm_developer_proc_clean(void); -#endif // DSMM_DEVELOPER_H +/** + * get_developer_mode_state - Get developer state of the device. + * + * @state: State of the device. + * + * Returns the developer state, STATE_ON or STATE_OFF. + */ +int get_developer_mode_state(void); + +#endif /* _DSMM_DEVELOPER_H */ diff --git a/xpm/validator/exec_signature_info.c b/xpm/validator/exec_signature_info.c index c2282eb..1047af9 100644 --- a/xpm/validator/exec_signature_info.c +++ b/xpm/validator/exec_signature_info.c @@ -218,7 +218,7 @@ static bool dm_verity_is_enable(void) dm_verity_enable_check = true; if (!dm_verity_enable) { dm_partition_table[0].s_dev = get_root_partition_dev(&root_path); - report_init_event(TYPE_DM_DISABLE); + report_init_event(DM_DISABLE); } return dm_verity_enable; } @@ -246,7 +246,7 @@ static bool is_dm_verity(struct file *file) if (!dm_verity_enable_check) { dm_partition_table[0].s_dev = get_root_partition_dev(&root_path); dm_verity_enable_check = true; - report_init_event(TYPE_DM_DISABLE); + report_init_event(DM_DISABLE); } return dm_verity_check_for_path(file); } @@ -267,7 +267,7 @@ static bool is_fs_verity(struct file *file) } #endif -static int check_exec_file_is_verity(struct file *file) +static int check_exec_file_is_verity(struct file *file, bool is_exec) { #ifdef CONFIG_FS_VERITY if (is_fs_verity(file)) @@ -278,7 +278,7 @@ static int check_exec_file_is_verity(struct file *file) return FILE_SIGNATURE_DM_VERITY; #ifdef CONFIG_SECURITY_CODE_SIGN - if (!elf_file_enable_fs_verity(file)) + if (is_exec && !elf_file_enable_fs_verity(file)) return FILE_SIGNATURE_FS_VERITY; #endif @@ -531,8 +531,10 @@ need_parse: return -ENOMEM; } else { ret = parse_elf_code_segment_info(file, &new_info); - if (ret < 0) + if (ret < 0) { + report_file_event(FORMAT_UNDEF, file); return ret; + } #ifdef CONFIG_SECURITY_XPM_DEBUG test_print_info(file, type, new_info); #endif @@ -555,7 +557,7 @@ int get_exec_file_signature_info(struct file *file, bool is_exec, if (file == NULL || info_ptr == NULL) return -EINVAL; - type = check_exec_file_is_verity(file); + type = check_exec_file_is_verity(file, is_exec); return get_elf_code_segment_info(file, is_exec, type, info_ptr); } diff --git a/xpm/include/exec_signature_info.h b/xpm/validator/exec_signature_info.h similarity index 100% rename from xpm/include/exec_signature_info.h rename to xpm/validator/exec_signature_info.h -- Gitee