diff --git a/LICENSE b/LICENSE index 28a5856373cce52c59708ad93f38842cd6dd5082..4c36850966c935deda828eb3b50956da3766f1dc 100644 --- a/LICENSE +++ b/LICENSE @@ -5,5 +5,6 @@ ./ucollection/ ./memory_security/ ./code_sign + ./container_escape_detection 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 7235b7bd33458cfca44d02fffe3cde93af32c55d..ba945ca6b68c66624221a55b66ecf2f78ea2be62 100644 --- a/OAT.xml +++ b/OAT.xml @@ -63,12 +63,14 @@ Note:If the text contains special characters, please escape them according to th + + diff --git a/container_escape_detection/Kconfig b/container_escape_detection/Kconfig new file mode 100644 index 0000000000000000000000000000000000000000..9fc3c2fdc3de6f1a43d7a94f013cd6da583dd850 --- /dev/null +++ b/container_escape_detection/Kconfig @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2023 Huawei Device Co., Ltd. +# +config SECURITY_CONTAINER_ESCAPE_DETECTION + bool "Enable container escape detection" + default n + depends on SECURITY_SELINUX + help + Build support for container escape detection. diff --git a/container_escape_detection/Makefile b/container_escape_detection/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3fd48e618fc5241aa35b1d96d2fdb8820de422f8 --- /dev/null +++ b/container_escape_detection/Makefile @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) 2023 Huawei Device Co., Ltd. +# +obj-$(CONFIG_SECURITY_CONTAINER_ESCAPE_DETECTION) += core/ced_detection.o +obj-$(CONFIG_SECURITY_CONTAINER_ESCAPE_DETECTION) += core/ced_module.o + +ccflags-$(CONFIG_SECURITY_CONTAINER_ESCAPE_DETECTION) := \ + -I$(srctree)/security/container_escape_detection/include \ + -I$(srctree)/security/selinux/include + +$(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/container_escape_detection/apply_ced.sh b/container_escape_detection/apply_ced.sh new file mode 100755 index 0000000000000000000000000000000000000000..2d34691a0337cbe08f405dce0eefe0ad3c9fe673 --- /dev/null +++ b/container_escape_detection/apply_ced.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 +CED_SOURCE_ROOT=$OHOS_SOURCE_ROOT/kernel/linux/common_modules/container_escape_detection + +function main() +{ + pushd . + + if [ ! -d " $KERNEL_BUILD_ROOT/security/container_escape_detection" ]; then + mkdir $KERNEL_BUILD_ROOT/security/container_escape_detection + fi + + cd $KERNEL_BUILD_ROOT/security/container_escape_detection + ln -s -f $(realpath --relative-to=$KERNEL_BUILD_ROOT/security/container_escape_detection/ $CED_SOURCE_ROOT)/* ./ + + popd +} + +main diff --git a/container_escape_detection/core/ced_detection.c b/container_escape_detection/core/ced_detection.c new file mode 100644 index 0000000000000000000000000000000000000000..3981b4d082c232c6f94ba7cc784180999c0ed41b --- /dev/null +++ b/container_escape_detection/core/ced_detection.c @@ -0,0 +1,128 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include "ced_log.h" +#include "avc.h" +#include "objsec.h" +#include "ced_detection.h" + +enum ced_event_type { + EVENT_CRED_ROOT, + EVENT_NSPROXY_ROOT, + EVENT_HAS_ROOT, + EVENT_NUM +}; + +extern struct task_struct init_task; + +static const char *gEventContent[EVENT_NUM] = { + "cred has been changed to root.", + "nsproxy has been changed to init.", + "process has been rooted." +}; + +static inline void print_container_escape_detection(enum ced_event_type type) +{ + if (type < EVENT_NUM) { + ced_log_error("tgid is %d, %s container escape is detected!!!!", current->tgid, gEventContent[type]); + } +} + +static int ced_avc_has_perm(u16 tclass, u32 requested) +{ + struct av_decision avd; + u32 sid = current_sid(); + int rc; + + rc = avc_has_perm_noaudit(&selinux_state, sid, sid, tclass, requested, + AVC_STRICT, &avd); + + return rc; +} + +static bool ced_has_check_perm(void) +{ + // use selinux label to tell the process is hap process + int rc = ced_avc_has_perm(SECCLASS_CED, CED__CONTAINER_ESCAPE_CHECK); + if (rc) { + return false; + } + + return true; +} + +static uint64_t process_ns_pac_hash(const struct nsproxy *nsproxy) +{ + uint64_t pac_hash = 0; + uintptr_t ns_ptr = (uintptr_t)nsproxy->mnt_ns; + pac_hash ^= ns_ptr; + ns_ptr = (uintptr_t)nsproxy->pid_ns_for_children; + pac_hash ^= ns_ptr; + ns_ptr = (uintptr_t)nsproxy->net_ns; + pac_hash ^= ns_ptr; + return pac_hash; +} + +static bool is_container_process(const struct nsproxy *new) +{ + uint64_t current_pac_hash = process_ns_pac_hash(new); + uint64_t init_task_ns_pac = process_ns_pac_hash(init_task.nsproxy); + if (current_pac_hash == init_task_ns_pac) { + return false; + } else { + return true; + } +} + +static bool detection_promotion_privilege(const struct cred *new) +{ + const struct cred *init_cred = get_task_cred(&init_task); + bool flag = false; + if (new->euid.val == 0 || new->egid.val == 0 || new->fsuid.val == 0 + || !memcmp(&new->cap_effective, &init_cred->cap_effective, sizeof(kernel_cap_t))) { + flag = true; + } + return flag; +} + +void switch_task_namespaces_hook(const struct nsproxy *new) +{ + if (!ced_has_check_perm()) { + return; + } + + if (new == NULL) { + return; + } + + if (!is_container_process(new)) { + print_container_escape_detection(EVENT_NSPROXY_ROOT); + } +} + +void commit_creds_hook(const struct cred *new) +{ + if (!ced_has_check_perm()) { + return; + } + + if (detection_promotion_privilege(new)) { + print_container_escape_detection(EVENT_CRED_ROOT); + } +} + +void detection_hook(struct task_struct *task) +{ + if (!ced_has_check_perm()) { + return; + } + + const struct cred *cred = get_task_cred(task); + + if ((!is_container_process(task->nsproxy) || (detection_promotion_privilege(cred)))) { + print_container_escape_detection(EVENT_HAS_ROOT); + } +} \ No newline at end of file diff --git a/container_escape_detection/core/ced_module.c b/container_escape_detection/core/ced_module.c new file mode 100644 index 0000000000000000000000000000000000000000..2e35464ee47f08f7b08ad9f7c02ca9b4db3b6bd6 --- /dev/null +++ b/container_escape_detection/core/ced_module.c @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#include +#include +#include "ced_detection.h" +#include "ced_log.h" + +void ced_register_ced_hooks(void) +{ + REGISTER_HCK_LITE_HOOK(ced_detection_lhck, detection_hook); + REGISTER_HCK_LITE_HOOK(ced_switch_task_namespaces_lhck, switch_task_namespaces_hook); + REGISTER_HCK_LITE_HOOK(ced_commit_creds_lhck, commit_creds_hook); + ced_log_info("ced_register_ced_hooks"); +} + +static int __init ced_module_init(void) +{ + ced_register_ced_hooks(); + return 0; +} + +module_init(ced_module_init); +MODULE_LICENSE("GPL"); \ No newline at end of file diff --git a/container_escape_detection/include/ced_detection.h b/container_escape_detection/include/ced_detection.h new file mode 100644 index 0000000000000000000000000000000000000000..aed4f5d27da3b51d192e407353d3d0912f0b7a0f --- /dev/null +++ b/container_escape_detection/include/ced_detection.h @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _CED_DETECTION_H +#define _CED_DETECTION_H + +#include +#include + +void detection_hook(struct task_struct *task); +void switch_task_namespaces_hook(const struct nsproxy *new); +void commit_creds_hook(const struct cred *new); + +#endif /* _CED_DETECTION_H */ \ No newline at end of file diff --git a/container_escape_detection/include/ced_log.h b/container_escape_detection/include/ced_log.h new file mode 100644 index 0000000000000000000000000000000000000000..89b17c6ced74f0f8abb67f94b3c47573fa856ae3 --- /dev/null +++ b/container_escape_detection/include/ced_log.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (c) 2023 Huawei Device Co., Ltd. + */ + +#ifndef _CED_LOG_H +#define _CED_LOG_H + +#define CED_CHECK_FAILED (-1024) + +#define CED_TAG "ced_kernel" +#define CED_INFO_TAG "I" +#define CED_ERROR_TAG "E" +#define CED_DEBUG_TAG "D" + +#define ced_log_info(fmt, args...) pr_info("[%s/%s]%s: " fmt "\n", \ + CED_INFO_TAG, CED_TAG, __func__, ##args) + +#define ced_log_error(fmt, args...) pr_err("[%s/%s]%s: " fmt "\n", \ + CED_ERROR_TAG, CED_TAG, __func__, ##args) + +#endif /* _CED_LOG_H */ \ No newline at end of file