113 lines
3.8 KiB
C
113 lines
3.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (C) 2021 MediaTek Inc.
|
|
*/
|
|
|
|
#include "policy.h"
|
|
|
|
DEBUG_SET_LEVEL(DEBUG_LEVEL_ERR);
|
|
|
|
/* Threshold of warning count */
|
|
#define MAX_WARNING_COUNT (3)
|
|
static atomic_t policy_violations[MKP_POLICY_NR];
|
|
static int panic_on __ro_after_init;
|
|
|
|
int __ro_after_init policy_ctrl[MKP_POLICY_NR];
|
|
uint32_t __ro_after_init mkp_policy_action[MKP_POLICY_NR] = {
|
|
/* Policy Table */
|
|
[MKP_POLICY_MKP] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | NO_UPGRADE_TO_EXEC | HANDLE_PERMANENT | ACTION_PANIC),
|
|
[MKP_POLICY_DRV] = (NO_MAP_TO_DEVICE | ACTION_PANIC),
|
|
[MKP_POLICY_SELINUX_STATE] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | HANDLE_PERMANENT | ACTION_PANIC),
|
|
[MKP_POLICY_SELINUX_AVC] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | HANDLE_PERMANENT | SB_ENTRY_DISORDERED | ACTION_WARNING),
|
|
[MKP_POLICY_TASK_CRED] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | HANDLE_PERMANENT | SB_ENTRY_ORDERED | ACTION_WARNING),
|
|
[MKP_POLICY_KERNEL_CODE] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | HANDLE_PERMANENT | ACTION_WARNING),
|
|
[MKP_POLICY_KERNEL_RODATA] = (NO_MAP_TO_DEVICE | NO_UPGRADE_TO_WRITE | HANDLE_PERMANENT | ACTION_WARNING),
|
|
[MKP_POLICY_KERNEL_PAGES] = (0x0 | ACTION_NOTIFICATION),
|
|
[MKP_POLICY_PGTABLE] = (0x0),
|
|
[MKP_POLICY_S1_MMU_CTRL] = (0x0),
|
|
[MKP_POLICY_FILTER_SMC_HVC] = (0x0),
|
|
};
|
|
void __init set_policy(u32 policy)
|
|
{
|
|
MKP_INFO("MKP: set policy start...\n");
|
|
memset(policy_ctrl, 0, MKP_POLICY_NR*sizeof(int));
|
|
|
|
/* default enable all policy */
|
|
/* MKP default policies (0 ~ 15) */
|
|
policy_ctrl[MKP_POLICY_MKP] = policy & BIT(MKP_POLICY_MKP);
|
|
policy_ctrl[MKP_POLICY_DRV] = policy & BIT(MKP_POLICY_DRV);
|
|
policy_ctrl[MKP_POLICY_SELINUX_STATE] = policy & BIT(MKP_POLICY_SELINUX_STATE);
|
|
policy_ctrl[MKP_POLICY_SELINUX_AVC] = policy & BIT(MKP_POLICY_SELINUX_AVC);
|
|
policy_ctrl[MKP_POLICY_TASK_CRED] = policy & BIT(MKP_POLICY_TASK_CRED);
|
|
policy_ctrl[MKP_POLICY_KERNEL_CODE] = policy & BIT(MKP_POLICY_KERNEL_CODE);
|
|
policy_ctrl[MKP_POLICY_KERNEL_RODATA] = policy & BIT(MKP_POLICY_KERNEL_RODATA);
|
|
policy_ctrl[MKP_POLICY_KERNEL_PAGES] = policy & BIT(MKP_POLICY_KERNEL_PAGES);
|
|
policy_ctrl[MKP_POLICY_PGTABLE] = policy & BIT(MKP_POLICY_PGTABLE);
|
|
policy_ctrl[MKP_POLICY_S1_MMU_CTRL] = policy & BIT(MKP_POLICY_S1_MMU_CTRL);
|
|
policy_ctrl[MKP_POLICY_FILTER_SMC_HVC] = policy & BIT(MKP_POLICY_FILTER_SMC_HVC);
|
|
|
|
/* Policies for vendors start from here (16 ~ 31) */
|
|
policy_ctrl[MKP_POLICY_VENDOR_START] = policy & BIT(MKP_POLICY_VENDOR_START);
|
|
MKP_INFO("MKP: set policy Done\n");
|
|
}
|
|
|
|
int __init set_ext_policy(uint32_t policy)
|
|
{
|
|
if ((int)policy < 0 || policy >= MKP_POLICY_NR) {
|
|
MKP_WARN("policy:%d is Out-of-bound\n", (int)policy);
|
|
return -1;
|
|
} else if (policy <= MKP_POLICY_DEFAULT_MAX) {
|
|
MKP_WARN("policy:%u is duplicated\n", policy);
|
|
return -1;
|
|
}
|
|
|
|
policy_ctrl[policy] = 1;
|
|
return 0;
|
|
}
|
|
|
|
void __init enable_action_panic(void)
|
|
{
|
|
pr_info("%s: enable mkp panic\n", __func__);
|
|
panic_on = 1;
|
|
}
|
|
|
|
static void do_policy_action_panic(uint32_t policy)
|
|
{
|
|
pr_alert("%s for policy:%u\n", __func__, policy);
|
|
|
|
/* Is action_panic enabled */
|
|
if (!panic_on)
|
|
return;
|
|
|
|
// For now we use warn for panic.
|
|
panic("mkp action panic for policy:%u\n", policy);
|
|
}
|
|
|
|
static void do_policy_action_warning(uint32_t policy)
|
|
{
|
|
pr_alert("%s for policy:%u\n", __func__, policy);
|
|
|
|
/* Is action_panic enabled */
|
|
if (!panic_on)
|
|
return;
|
|
|
|
if (atomic_add_return(1, &policy_violations[policy]) > MAX_WARNING_COUNT)
|
|
panic("mkp action warning exceeds threshold for policy:%u\n", policy);
|
|
}
|
|
|
|
void handle_mkp_err_action(uint32_t policy)
|
|
{
|
|
if ((int)policy < 0 || policy >= MKP_POLICY_NR)
|
|
return;
|
|
|
|
if (mkp_policy_action[policy] & ACTION_PANIC) {
|
|
MKP_ERR("mkp error\n");
|
|
do_policy_action_panic(policy);
|
|
} else if (mkp_policy_action[policy] & ACTION_WARNING) {
|
|
MKP_WARN("mkp warning\n");
|
|
do_policy_action_warning(policy);
|
|
} else {
|
|
/* just notification */
|
|
MKP_INFO("mkp error\n");
|
|
}
|
|
}
|