新增容器逃逸检测模块

Signed-off-by: xiacong <xiacong4@huawei.com>
Change-Id: Ib9a158b9bf965bcf1cd28786c25a50fe718a6690
Signed-off-by: xiacong <xiacong4@huawei.com>
This commit is contained in:
xiacong
2023-11-14 11:08:08 +08:00
parent 44e934265f
commit 5ceb44f5f4
9 changed files with 250 additions and 0 deletions
+1
View File
@@ -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.
+2
View File
@@ -63,12 +63,14 @@ Note:If the text contains special characters, please escape them according to th
<policyitem type="compatibility" name="GPL" path="qos_auth/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="ucollection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="code_sign/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="compatibility" name="GPL" path="container_escape_detection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="newip/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="xpm/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="memory_security/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="qos_auth/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="ucollection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="code_sign/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
<policyitem type="license" name="GPL" path="container_escape_detection/.*" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
</policy>
</policylist>
<filefilterlist>
+9
View File
@@ -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.
+18
View File
@@ -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)
+28
View File
@@ -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
@@ -0,0 +1,128 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/fs_struct.h>
#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);
}
}
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
*/
#include <linux/module.h>
#include <linux/hck/lite_hck_ced.h>
#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");
@@ -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 <linux/cred.h>
#include <linux/sched.h>
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 */
@@ -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 */