diff --git a/LICENSE b/LICENSE index 8eddf19d0568ff3af1bcd1ca9163e875da8cbc0d..21795c929b88afa5e7b1a2a84e620d9cf123b910 100644 --- a/LICENSE +++ b/LICENSE @@ -9,5 +9,6 @@ ./container_escape_detection ./module_sample ./pac/ + ./dec As for the specific use of the licenses, please refer to the relevant description in the documents. diff --git a/OAT.xml b/OAT.xml index f4ef13823b6d0d5a44d2d5a611e565e8231992e8..dfa276cdb30319b153acd22e192be2350b397128 100644 --- a/OAT.xml +++ b/OAT.xml @@ -66,7 +66,9 @@ Note:If the text contains special characters, please escape them according to th - + + + @@ -76,7 +78,9 @@ Note:If the text contains special characters, please escape them according to th - + + + @@ -99,7 +103,8 @@ Note:If the text contains special characters, please escape them according to th - + + diff --git a/code_sign/code_sign_elf.c b/code_sign/code_sign_elf.c index 9c9a3dccffd6692d261c26a639eecffe4c093492..0745061b11aea5ef4086549b35e9ba362d20f3a0 100644 --- a/code_sign/code_sign_elf.c +++ b/code_sign/code_sign_elf.c @@ -4,14 +4,22 @@ */ #include +#include #include #include -#include "dsmm_developer.h" +#if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 6, 0) +#include +#endif + #include "code_sign_elf.h" #include "code_sign_log.h" #include "verify_cert_chain.h" +#ifdef CONFIG_SECURITY_XPM +#include "dsmm_developer.h" +#endif + #define SIGN_HEAD_SIZE (sizeof(sign_head_t)) static void parse_sign_head(sign_head_t *out, char *ptr) @@ -197,12 +205,20 @@ out: int elf_file_enable_fs_verity(struct file *file) { +#ifdef CONFIG_SECURITY_XPM /* developer mode */ if (get_developer_mode_state() != STATE_ON) { code_sign_log_info("developer mode off, elf not allowed to execute"); return -EINVAL; } +#else + code_sign_log_info("developer mode off, elf not allowed to execute"); + return -EINVAL; +#endif + +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) mm_segment_t fs; +#endif char *path_buf = kzalloc(PATH_MAX, GFP_KERNEL); if (!path_buf) { code_sign_log_error("alloc mem for path_buf failed"); @@ -245,10 +261,10 @@ int elf_file_enable_fs_verity(struct file *file) err = -ENOMEM; goto filp_close_out; } - +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) fs = get_fs(); set_fs(KERNEL_DS); - +#endif ssize_t cnt = vfs_read(fp, sign_head_ptr, SIGN_HEAD_SIZE, &pos); if (cnt != SIGN_HEAD_SIZE) { code_sign_log_error("read sign head from file failed: return value %lu, expect %u bytes", @@ -278,7 +294,9 @@ int elf_file_enable_fs_verity(struct file *file) release_sign_head_out: kfree(sign_head_ptr); +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) set_fs(fs); +#endif filp_close_out: filp_close(fp, NULL); release_path_buf_out: diff --git a/code_sign/code_sign_ext.c b/code_sign/code_sign_ext.c index afe042278473faa5d1b794d8c8ec62856332e1be..16abbaf803ceb3eb8429e090f4e0c99f35ceaf34 100644 --- a/code_sign/code_sign_ext.c +++ b/code_sign/code_sign_ext.c @@ -24,10 +24,14 @@ static inline int check_code_sign_descriptor(const struct inode *inode, if (!desc->cs_version) return 0; - - if (desc->__reserved1 || - memchr_inv(desc->__reserved2, 0, sizeof(desc->__reserved2))) + + // when calc pgtypeinfo_size, trans bit size to byte size + u32 pgtypeinfo_size_bytes = le32_to_cpu(desc->pgtypeinfo_size) / 8; + if (le64_to_cpu(desc->pgtypeinfo_off) > le64_to_cpu(desc->data_size) - pgtypeinfo_size_bytes) { + code_sign_log_error("Wrong offset: %llu (pgtypeinfo_off) > %llu (data_size) - %u (pgtypeinfo_size)", + le64_to_cpu(desc->pgtypeinfo_off), le64_to_cpu(desc->data_size), pgtypeinfo_size_bytes); return -EINVAL; + } if (le64_to_cpu(desc->data_size) > inode->i_size) { code_sign_log_error("Wrong data_size: %llu (desc) > %lld (inode)", @@ -67,11 +71,11 @@ void code_sign_before_measurement(void *_desc, int *ret) { struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); - if (desc->cs_version) { - // replace version with cs_version - desc->version = desc->cs_version; + if (desc->cs_version == 1) { + *ret = desc->cs_version; desc->cs_version = 0; - *ret = desc->version; + } else { + *ret = desc->cs_version; } } @@ -79,7 +83,7 @@ void code_sign_after_measurement(void *_desc, int version) { struct code_sign_descriptor *desc = CAST_CODE_SIGN_DESC(_desc); - if (version) { + if (version == 1) { // restore cs_version desc->cs_version = desc->version; desc->version = version; diff --git a/code_sign/code_sign_ioctl.c b/code_sign/code_sign_ioctl.c index 16e640c6a648268ab8af7a35d9f7ed10254cac24..8e2efdd221ac4fbb699d02792cedfeb551f1a12a 100644 --- a/code_sign/code_sign_ioctl.c +++ b/code_sign/code_sign_ioctl.c @@ -8,11 +8,12 @@ #include #include #include +#include #include "avc.h" #include "objsec.h" -#include "dsmm_developer.h" #include "code_sign_ioctl.h" #include "code_sign_log.h" +#define MAX_SIGNING_LENGTH 2048 DEFINE_SPINLOCK(cert_chain_tree_lock); struct rb_root cert_chain_tree = RB_ROOT; @@ -71,8 +72,11 @@ int code_sign_check_caller(char *caller) u32 sid = current_sid(), context_len; char *context = NULL; int rc; - +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) rc = security_sid_to_context(&selinux_state, sid, &context, &context_len); +#else + rc = security_sid_to_context(sid, &context, &context_len); +#endif if (rc) return -EINVAL; @@ -180,11 +184,17 @@ int code_sign_avc_has_perm(u16 tclass, u32 requested) struct av_decision avd; u32 sid = current_sid(); int rc, rc2; - +#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0) 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); +#else + rc = avc_has_perm_noaudit(sid, sid, tclass, requested, + AVC_STRICT, &avd); + rc2 = avc_audit(sid, sid, tclass, requested, &avd, rc, + NULL); +#endif if (rc2) return rc2; @@ -207,13 +217,14 @@ int parse_cert_source(unsigned long args, struct cert_source **_source) goto copy_source_failed; } - if (info.path_len > CERT_CHAIN_PATH_LEN_MAX || info.issuer_length == 0 || info.signing_length == 0) { + if (info.path_len > CERT_CHAIN_PATH_LEN_MAX || info.issuer_length == 0 || info.signing_length == 0 + || info.issuer_length > MAX_SIGNING_LENGTH || info.signing_length > MAX_SIGNING_LENGTH) { code_sign_log_error("invalid path len or subject or issuer"); ret = -EINVAL; goto copy_source_failed; } - source->subject = kzalloc(info.signing_length, GFP_KERNEL); + source->subject = kzalloc(info.signing_length + 1, GFP_KERNEL); if (!source->subject) { ret = -ENOMEM; goto copy_source_failed; @@ -225,7 +236,7 @@ int parse_cert_source(unsigned long args, struct cert_source **_source) goto copy_subject_failed; } - source->issuer = kzalloc(info.issuer_length, GFP_KERNEL); + source->issuer = kzalloc(info.issuer_length + 1, GFP_KERNEL); if (!source->issuer) { ret = -ENOMEM; goto copy_subject_failed; @@ -288,10 +299,8 @@ long code_sign_ioctl(struct file *filp, unsigned int cmd, unsigned long args) if (ret == 1) { // developer cert - if (get_developer_mode_state() == STATE_ON) { - code_sign_log_debug("add developer cert"); - ret = cert_chain_insert(&dev_cert_chain_tree, source); - } + code_sign_log_debug("add developer cert"); + ret = cert_chain_insert(&dev_cert_chain_tree, source); } else { code_sign_log_debug("add release cert"); ret = cert_chain_insert(&cert_chain_tree, source); @@ -314,10 +323,8 @@ long code_sign_ioctl(struct file *filp, unsigned int cmd, unsigned long args) if (ret == 1) { // developer cert - if (get_developer_mode_state() == STATE_ON) { - code_sign_log_debug("remove developer cert"); - ret = cert_chain_remove(&dev_cert_chain_tree, source); - } + code_sign_log_debug("remove developer cert"); + ret = cert_chain_remove(&dev_cert_chain_tree, source); } else { code_sign_log_debug("remove release cert"); ret = cert_chain_remove(&cert_chain_tree, source); diff --git a/code_sign/verify_cert_chain.c b/code_sign/verify_cert_chain.c index 908dd6babb36cd9abf191993ad4dd1757a64498c..3e9d096777bcc22300d4d8b679475df8703548a9 100644 --- a/code_sign/verify_cert_chain.c +++ b/code_sign/verify_cert_chain.c @@ -6,15 +6,19 @@ #include #include #include +#include #include #include #include "objsec.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" +#ifdef CONFIG_SECURITY_XPM +#include "dsmm_developer.h" +#endif + /* * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 * uses the issuer's name and the issuing certificate serial number for @@ -144,11 +148,13 @@ void code_sign_verify_certchain(const void *raw_pkcs7, size_t pkcs7_len, bool is_dev_mode = false; +#ifdef CONFIG_SECURITY_XPM // developer mode && developer proc if (get_developer_mode_state() == STATE_ON) { code_sign_log_info("developer mode on"); is_dev_mode = true; } +#endif for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { /* Find the key for the signature if there is one */ diff --git a/container_escape_detection/core/ced_detection.c b/container_escape_detection/core/ced_detection.c index 3f0ff8c6d20d42299720bedc7df80204cbdc49c1..b8f291715ca41979e2459e5e65760144ac2a8b62 100644 --- a/container_escape_detection/core/ced_detection.c +++ b/container_escape_detection/core/ced_detection.c @@ -9,6 +9,7 @@ #include "objsec.h" #include "ced_detection.h" #include "ced_detection_points.h" +#include enum ced_event_type { EVENT_OK, @@ -40,13 +41,21 @@ static int ced_avc_has_perm(u16 tclass, u32 requested) struct av_decision avd; int rc; +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) if (!selinux_initialized(&selinux_state)) return 1; - +#else + if (!selinux_initialized()) + return 1; +#endif u32 sid = current_sid(); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) rc = avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, AVC_STRICT, &avd); - +#else + rc = avc_has_perm_noaudit(sid, sid, tclass, requested, + AVC_STRICT, &avd); +#endif return rc; } diff --git a/container_escape_detection/include/ced_detection_points.h b/container_escape_detection/include/ced_detection_points.h index 45eb2babca36f19bb75c7d1c26ec652528e9314d..cf62cb285b8296df7dab88c3866c9ce7ef8f137d 100644 --- a/container_escape_detection/include/ced_detection_points.h +++ b/container_escape_detection/include/ced_detection_points.h @@ -29,7 +29,7 @@ static inline void cred_info_record(struct cred_info *info, const struct cred *c info->egid = cred->egid.val; info->fsuid = cred->fsuid.val; - memcpy(&info->cap_effective.cap[0], &cred->cap_effective.cap[0], sizeof(info->cap_effective.cap)); + memcpy(&info->cap_effective, &cred->cap_effective, sizeof(kernel_cap_t)); } struct ns_info { diff --git a/dec/Kconfig b/dec/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..9f9cbda17d8db0c87fcb90434d4a5b9d82705277 --- /dev/null +++ b/dec/Kconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2024 Huawei Device Co., Ltd. +# +config SECURITY_DEC + bool "Data enhance control features" + + default y + help + This option enables file operation permission verification + at VFS layer. + + If unsure, say N. diff --git a/dec/Makefile b/dec/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..efd9cfef5993875569cbca81e83f99d476f471b7 --- /dev/null +++ b/dec/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2024 Huawei Device Co., Ltd. +# +obj-$(CONFIG_SECURITY_DEC) += \ + dec_misc.o + +ccflags-$(CONFIG_SECURITY_DEC) += \ + -I$(srctree)/fs/dec + +$(addprefix $(obj)/,$(obj-y)): $(obj)/flask.h + +quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h + cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h + +targets += flask.h av_permissions.h +$(obj)/flask.h: $(srctree)/security/selinux/include/classmap.h FORCE + $(call if_changed,flask) diff --git a/dec/apply_dec.sh b/dec/apply_dec.sh new file mode 100644 index 0000000000000000000000000000000000000000..6f63fb5e8d525b0bec012df1732819a53e08cdfc --- /dev/null +++ b/dec/apply_dec.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2023 Huawei Device Co., Ltd. +# + +set -e + +OHOS_SOURCE_ROOT=$1 +KERNEL_BUILD_ROOT=$2 +PRODUCT_NAME=$3 +KERNEL_VERSION=$4 +DEC_SOURCE_ROOT=$OHOS_SOURCE_ROOT/kernel/linux/common_modules/dec + +function main() +{ + pushd . + + if [ ! -d "$KERNEL_BUILD_ROOT/fs/dec" ]; then + mkdir $KERNEL_BUILD_ROOT/fs/dec + fi + + cd $KERNEL_BUILD_ROOT/fs/dec + ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/fs/dec $DEC_SOURCE_ROOT)/* ./ + + popd +} + +main diff --git a/dec/dec_misc.c b/dec/dec_misc.c new file mode 100644 index 0000000000000000000000000000000000000000..534ce5ce622bf8c82e28feefafbad0c13945fd12 --- /dev/null +++ b/dec/dec_misc.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include + +#include "dec_misc.h" + +static int vfs_deal_policy_cmd(unsigned int cmd, void __user *arg) +{ + pr_info("vfs dec deal policy cmd:%u\n", cmd); + int ret = 0; + struct dec_policy_info info = { 0 }; + + ret = copy_from_user(&info, arg, sizeof(info)); + if (ret != 0) { + pr_err("copy from user failed\n"); + return -EFAULT; + } + + pr_info("tokenid:%lu path_num:%u persist_flag:%d\n", info.tokenid, info.path_num, info.persist_flag); + + return ret; +} + +static int vfs_destroy_dec_policy(void __user *arg) +{ + int ret = 0; + uint64_t tokenid; + + ret = copy_from_user(&tokenid, arg, sizeof(tokenid)); + if (ret != 0) { + pr_err("destroy dec policy copy from caller failed\n"); + return -EFAULT; + } + + pr_info("destroy dec policy tokenid:%ld\n", tokenid); + return 0; +} + +static long dec_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + pr_info("dec ioctl cmd:%u\n", cmd); + int ret = 0; + + switch (cmd) { + case SET_DEC_POLICY_CMD: + case DEL_DEC_POLICY_CMD: + case QUERY_DEC_POLICY_CMD: + case CHECK_DEC_POLICY_CMD: + case CONSTRAINT_DEC_POLICY_CMD: + case DENY_DEC_POLICY_CMD: + ret = vfs_deal_policy_cmd(cmd, (void __user *)arg); + break; + case DESTROY_DEC_POLICY_CMD: + ret = vfs_destroy_dec_policy((void __user *)arg); + break; + default: + ret = -EINVAL; + break; + } + + return 0; +} + +static int dec_open(struct inode *inode, struct file *filp) +{ + pr_info("dec open\n"); + return 0; +} + +static int dec_release(struct inode *inode, struct file *filp) +{ + pr_info("dec close\n"); + return 0; +} + +static const struct file_operations dec_fops = { + .owner = THIS_MODULE, + .open = dec_open, + .release = dec_release, + .unlocked_ioctl = dec_ioctl, + .compat_ioctl = dec_ioctl, +}; + +static struct miscdevice dec_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "dec", + .fops = &dec_fops, +}; + +static int __init dec_init(void) +{ + int err = 0; + + err = misc_register(&dec_misc); + if (err < 0) { + pr_err("dec device init failed\n"); + return err; + } + + pr_err("dec device init success\n"); + return 0; +} + +static void __exit dec_exit(void) +{ + misc_deregister(&dec_misc); + pr_info("dec exited"); +} + +/* module entry points */ +module_init(dec_init); +module_exit(dec_exit); + +MODULE_LICENSE("GPL"); diff --git a/dec/dec_misc.h b/dec/dec_misc.h new file mode 100644 index 0000000000000000000000000000000000000000..1154ece0904126309605e2195957acd9689e8a0e --- /dev/null +++ b/dec/dec_misc.h @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + */ + +#ifndef _DEC_MISC_H +#define _DEC_MISC_H + +#include +#include +#include + +#define MAX_PATH_NUM 8 + +#define DEV_DEC_MINOR 0x25 +#define DEC_IOCTL_BASE 's' +#define SET_POLICY_ID 1 +#define DEL_POLICY_ID 2 +#define QUERY_POLICY_ID 3 +#define CHECK_POLICY_ID 4 +#define DESTROY_POLICY_ID 5 +#define CONSTRAINT_POLICY_ID 6 +#define DENY_POLICY_ID 7 + +struct path_info { + char* path; + uint32_t path_len; + uint32_t mode; + bool ret_flag; +}; + +struct dec_policy_info { + uint64_t tokenid; + struct path_info path[MAX_PATH_NUM]; + uint32_t path_num; + bool persist_flag; +}; + +#define SET_DEC_POLICY_CMD \ + _IOWR(DEC_IOCTL_BASE, SET_POLICY_ID, struct dec_policy_info) +#define DEL_DEC_POLICY_CMD \ + _IOWR(DEC_IOCTL_BASE, DEL_POLICY_ID, struct dec_policy_info) +#define QUERY_DEC_POLICY_CMD \ + _IOWR(DEC_IOCTL_BASE, QUERY_POLICY_ID, struct dec_policy_info) +#define CHECK_DEC_POLICY_CMD \ + _IOWR(DEC_IOCTL_BASE, CHECK_POLICY_ID, struct dec_policy_info) +#define CONSTRAINT_DEC_POLICY_CMD \ + _IOW(DEC_IOCTL_BASE, CONSTRAINT_POLICY_ID, struct dec_policy_info) +#define DENY_DEC_POLICY_CMD \ + _IOWR(DEC_IOCTL_BASE, DENY_POLICY_ID, struct dec_policy_info) +#define DESTROY_DEC_POLICY_CMD \ + _IOW(DEC_IOCTL_BASE, DESTROY_POLICY_ID, uint64_t) + +#endif /* _DEC_MISC_H */ \ No newline at end of file diff --git a/memory_security/src/hideaddr.c b/memory_security/src/hideaddr.c index c34bbcd38f4632eeb78c6db0e6a5373f7a948128..5d77c4e9e40a11f5454b22b0f0e984425d1fb215 100644 --- a/memory_security/src/hideaddr.c +++ b/memory_security/src/hideaddr.c @@ -17,6 +17,7 @@ #include "avc.h" #include "objsec.h" #include "hideaddr.h" +#include static bool is_anon_exec(struct vm_area_struct *vma) { @@ -44,8 +45,13 @@ static int hideaddr_avc_has_perm(u16 tclass, u32 requested, struct seq_file *m) u32 secid; security_cred_getsecid(task->cred, &secid); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) return avc_has_perm_noaudit(&selinux_state, secid, secid, tclass, requested, AVC_STRICT, &avd); +#else + return avc_has_perm_noaudit(secid, secid, tclass, requested, + AVC_STRICT, &avd); +#endif } static void hideaddr_header_prefix(unsigned long *start, unsigned long *end, diff --git a/memory_security/src/jit_memory.c b/memory_security/src/jit_memory.c index 0fc0bee268878a5715dfadaf1db3af6386f595a8..e34b6ab0cbe380bf5841bdb76be3d6e1d3339a84 100644 --- a/memory_security/src/jit_memory.c +++ b/memory_security/src/jit_memory.c @@ -11,6 +11,7 @@ #include "jit_space_list.h" #include "avc.h" #include "objsec.h" +#include DEFINE_SPINLOCK(list_lock); @@ -25,8 +26,13 @@ static bool jit_avc_has_perm(u16 tclass, u32 requested, struct task_struct *task u32 secid; security_cred_getsecid(task->cred, &secid); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) return (avc_has_perm_noaudit(&selinux_state, secid, secid, tclass, requested, AVC_STRICT, &avd) == 0); +#else + return (avc_has_perm_noaudit(secid, secid, tclass, requested, + AVC_STRICT, &avd) == 0); +#endif } void find_jit_memory(struct task_struct *task, unsigned long start, unsigned long size, int *err) diff --git a/qos_auth/include/auth_ctrl.h b/qos_auth/include/auth_ctrl.h index 3fa0be5586e768e4ca9d32631be970bad509378a..f2e04ee959666450efe3eece4a1e547df9c29178 100644 --- a/qos_auth/include/auth_ctrl.h +++ b/qos_auth/include/auth_ctrl.h @@ -14,7 +14,8 @@ #define SYSTEM_UID 1000 #define SUPER_UID SYSTEM_UID -#define super_uid(uid) (uid == ROOT_UID || uid == SYSTEM_UID) +#define RESOURCE_SCHEDULE_SERVICE_UID 1096 +#define super_uid(uid) (uid == ROOT_UID || uid == SYSTEM_UID || uid == RESOURCE_SCHEDULE_SERVICE_UID) enum ioctl_abi_format_auth{ AUTH_IOCTL_ABI_ARM32, diff --git a/ucollection/ucollection_process_cpu.c b/ucollection/ucollection_process_cpu.c index db12fbe786b4627622463bb0b63142bdc9617c9e..79d0cf8d41eaf54a857739c803ced1e1c4da9b42 100644 --- a/ucollection/ucollection_process_cpu.c +++ b/ucollection/ucollection_process_cpu.c @@ -96,6 +96,7 @@ static void get_thread_load(struct task_struct *task, int cur_count, do_div(utime, NS_TO_MS); do_div(stime, NS_TO_MS); thread_cpu_item.tid = task->pid; + strcpy(thread_cpu_item.name, task->comm); thread_cpu_item.cpu_usage_utime = utime; thread_cpu_item.cpu_usage_stime = stime; thread_cpu_item.cpu_load_time = 0; diff --git a/ucollection/unified_collection_data.h b/ucollection/unified_collection_data.h index 67e270fa488152d668575677652ddd18150e8669..e261dd9cf4bceafd66ffeb7434b19da4e69ebe73 100644 --- a/ucollection/unified_collection_data.h +++ b/ucollection/unified_collection_data.h @@ -39,6 +39,7 @@ struct ucollection_process_thread_count { struct ucollection_thread_cpu_item { int tid; + char name[16]; // 16 : max length of thread name unsigned long long cpu_usage_utime; unsigned long long cpu_usage_stime; unsigned long long cpu_load_time; diff --git a/xpm/core/xpm_security_hooks.c b/xpm/core/xpm_security_hooks.c index 5fe5b37757acce3295cc8190221bfc48bbba040c..bb60507f46ea969d8995823632173fce1cc5fee9 100644 --- a/xpm/core/xpm_security_hooks.c +++ b/xpm/core/xpm_security_hooks.c @@ -5,6 +5,7 @@ #include #include +#include #include "avc.h" #include "objsec.h" @@ -182,8 +183,13 @@ static int xpm_avc_has_perm(u16 tclass, u32 requested) struct av_decision avd; u32 sid = current_sid(); +#if (LINUX_VERSION_CODE < KERNEL_VERSION(6, 6, 0)) return avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, AVC_STRICT, &avd); +#else + return avc_has_perm_noaudit(sid, sid, tclass, requested, + AVC_STRICT, &avd); +#endif } static int xpm_validate_signature(struct vm_area_struct *vma, @@ -361,7 +367,7 @@ static int xpm_mprotect_check(struct vm_area_struct *vma, return xpm_common_check(vma, prot); } -static struct security_hook_list xpm_hooks[] __lsm_ro_after_init = { +static struct security_hook_list xpm_hooks[] __ro_after_init = { LSM_HOOK_INIT(mmap_region, xpm_mmap_check), LSM_HOOK_INIT(file_mprotect, xpm_mprotect_check), }; diff --git a/xpm/validator/elf_code_segment_info.c b/xpm/validator/elf_code_segment_info.c index dbbb1a0f95cbe39ff57681071be2f61237a477ea..385ad3c863fab2707fc29676e836d1a36966b3aa 100644 --- a/xpm/validator/elf_code_segment_info.c +++ b/xpm/validator/elf_code_segment_info.c @@ -225,7 +225,7 @@ static int get_elf64_info(struct elfhdr *elf_ehdr, struct elf_info *elf_info) return 0; } -static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info) +static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_info *elf_info, bool *skip) { uint16_t type; struct elfhdr *elf_ehdr = &elf_info->elf_ehdr; @@ -235,8 +235,11 @@ static int elf_check_and_get_code_segment_offset(struct file *file, struct elf_i if (ret < 0) return ret; - if (memcmp(elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0) - return -ENOEXEC; + if (memcmp(elf_ehdr->e_ident, ELFMAG, SELFMAG) != 0) { + // when the file is not an ELF file, skip checking + *skip = true; + return 0; + } type = elf16_get_value(elf_ehdr, elf_ehdr->e_type); if (type != ET_EXEC && type != ET_DYN) @@ -287,16 +290,52 @@ static int find_elf_code_segment_info(const char *phdr_info, struct elf_info *el return 0; } +static int handle_skip_case(struct file *file, struct exec_file_signature_info **code_segment_info) { + struct exec_file_signature_info *tmp_info = NULL; + if (*code_segment_info == NULL) { + tmp_info = kzalloc(sizeof(struct exec_file_signature_info), GFP_KERNEL); + if (tmp_info == NULL) { + return -ENOMEM; + } + } else { + tmp_info = *code_segment_info; + } + + if (tmp_info->code_segments == NULL) { + tmp_info->code_segments = kzalloc(sizeof(struct exec_segment_info), GFP_KERNEL); + if (tmp_info->code_segments == NULL) { + if (*code_segment_info == NULL) { + kfree(tmp_info); + tmp_info = NULL; + } + return -ENOMEM; + } + tmp_info->code_segment_count = 1; + } + + tmp_info->code_segments[0].file_offset = 0; + tmp_info->code_segments[0].size = file_inode(file)->i_size; + + if (*code_segment_info == NULL) { + *code_segment_info = tmp_info; + } + return 0; +} + int parse_elf_code_segment_info(struct file *file, struct exec_file_signature_info **code_segment_info) { const char *phdr_info; struct elf_info elf_info = {0}; int ret; - - ret = elf_check_and_get_code_segment_offset(file, &elf_info); + bool skip = false; + ret = elf_check_and_get_code_segment_offset(file, &elf_info, &skip); if (ret < 0) return ret; + + if (skip) { + return handle_skip_case(file, code_segment_info); + } phdr_info = kzalloc(elf_info.e_phsize, GFP_KERNEL); if (phdr_info == NULL) diff --git a/xpm/validator/exec_signature_info.c b/xpm/validator/exec_signature_info.c index 9c02c4ffaf60bb70b26367b4ac2e1c0644e99609..2d0f02e2462ce53c7a7cf9e60e15b7b29b9a4a0b 100644 --- a/xpm/validator/exec_signature_info.c +++ b/xpm/validator/exec_signature_info.c @@ -486,13 +486,15 @@ static void insert_new_signature_info(struct inode *file_node, int type, RB_CLEAR_NODE(&new_info->rb_node); if ((*old_info) != NULL) { write_lock(verity->lock); - rb_erase_node(verity->root, verity->node_count, *old_info); - (*old_info)->type |= FILE_SIGNATURE_DELETE; - write_unlock(verity->lock); - if (atomic_sub_return(1, &(*old_info)->reference) <= 0) { - kfree(*old_info); - *old_info = NULL; + if ((*old_info) != NULL) { + if (atomic_sub_return(1, &(*old_info)->reference) <= 0) { + rb_erase_node(verity->root, verity->node_count, *old_info); + (*old_info)->type |= FILE_SIGNATURE_DELETE; + kfree(*old_info); + *old_info = NULL; + } } + write_unlock(verity->lock); } write_lock(verity->lock);