virtcca inclusion category: feature bugzilla: https://gitee.com/openeuler/kernel/issues/I9TM0T
--------------------------------
enhance security for cvm host feature
Signed-off-by: Ju Fu fuju1@huawei.com --- arch/arm64/include/asm/kvm_emulate.h | 4 ++- arch/arm64/include/asm/kvm_tmi.h | 34 ++------------------ arch/arm64/include/asm/kvm_tmm.h | 2 +- arch/arm64/kvm/cvm.c | 48 ++++++++++++++++++++++++---- drivers/irqchip/irq-gic-v3-its.c | 2 +- 5 files changed, 49 insertions(+), 41 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 540563623..1271df56c 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -571,7 +571,9 @@ static inline enum cvm_state kvm_cvm_state(struct kvm *kvm) { struct cvm *cvm = kvm->arch.cvm;
- return cvm && READ_ONCE(cvm->state); + if (!cvm) + return 0; + return READ_ONCE(cvm->state); } #endif #endif /* __ARM64_KVM_EMULATE_H__ */ diff --git a/arch/arm64/include/asm/kvm_tmi.h b/arch/arm64/include/asm/kvm_tmi.h index 536594017..b89680f31 100644 --- a/arch/arm64/include/asm/kvm_tmi.h +++ b/arch/arm64/include/asm/kvm_tmi.h @@ -18,22 +18,6 @@ #define TMM_TTT_LEVEL_2 2 #define TMM_TTT_LEVEL_3 3
-#ifdef CONFIG_CVM_HOST_FVP_PLAT -#define CVM_MEM_BASE ULL(0x8800000000) /* choose FVP platform to run cVM */ -#define VQ_NUM 3 -#else -#define CVM_MEM_BASE ULL(0x800000000) /* choose qemu platform to run cVM */ -#define VQ_NUM 3 -#endif - -#define MEM_SEG_NUMS 2 - -/* define in QEMU hw/arm/virt.c */ -#define VIRT_PCIE_MMIO 0x10000000 /* 256MB */ -#define VIRT_PCIE_MMIO_SIZE 0x1000000 /* 16MB */ -#define VIRT_HIGH_PCIE_ECAM 0x8000000000 /* 512GB */ -#define VIRT_HIGH_PCIE_ECAM_SIZE 0x12000000 /* 288MB */ - /* TMI error codes. */ #define TMI_SUCCESS 0 #define TMI_ERROR_INPUT 1 @@ -214,6 +198,8 @@ struct tmi_tec_run { #define TMI_NO_MEASURE_CONTENT U(0) #define TMI_MEASURE_CONTENT U(1)
+#define CVM_IPA_MAX_VAL (1UL << 48) + /* * SMC_TMM_INIT_COMPLETE is the only function in the TMI that originates from * the CVM world and is handled by the SPMD. The remaining functions are @@ -264,7 +250,7 @@ struct tmi_tec_run { #define TMI_ABI_VERSION_GET_MAJOR(_version) ((_version) >> 16) #define TMI_ABI_VERSION_GET_MINOR(_version) ((_version) & 0xFFFF)
-#define TMI_ABI_VERSION_MAJOR U(0x0) +#define TMI_ABI_VERSION_MAJOR U(0x1)
/* KVM_CAP_ARM_TMM on VM fd */ #define KVM_CAP_ARM_TMM_CONFIG_CVM_HOST 0 @@ -330,20 +316,6 @@ struct kvm_cap_arm_tmm_populate_region_args { __u32 reserved[3]; };
-enum tmi_tmm_mem_type { - TMM_MEM_TYPE_RD, - TMM_MEM_TYPE_TEC, - TMM_MEM_TYPE_TTT, - TMM_MEM_TYPE_CVM_PA, -}; - -enum tmi_tmm_map_size { - TMM_MEM_MAP_SIZE_4K, - TMM_MEM_MAP_SIZE_2M, - TMM_MEM_MAP_SIZE_1G, - TMM_MEM_MAP_SIZE_MAX, -}; - static inline bool tmm_is_addr_ttt_level_aligned(uint64_t addr, int level) { uint64_t mask = (1 << (12 + 9 * (3 - level))) - 1; diff --git a/arch/arm64/include/asm/kvm_tmm.h b/arch/arm64/include/asm/kvm_tmm.h index 88fa0873c..8cc7a35c9 100644 --- a/arch/arm64/include/asm/kvm_tmm.h +++ b/arch/arm64/include/asm/kvm_tmm.h @@ -8,7 +8,7 @@ #include <uapi/linux/kvm.h>
enum cvm_state { - CVM_STATE_NONE, + CVM_STATE_NONE = 1, CVM_STATE_NEW, CVM_STATE_ACTIVE, CVM_STATE_DYING diff --git a/arch/arm64/kvm/cvm.c b/arch/arm64/kvm/cvm.c index 70521fec8..73b8daede 100644 --- a/arch/arm64/kvm/cvm.c +++ b/arch/arm64/kvm/cvm.c @@ -181,8 +181,9 @@ int kvm_arm_create_cvm(struct kvm *kvm) memcpy(cvm->params->rpv, &cvm->cvm_vmid, sizeof(cvm->cvm_vmid)); cvm->rd = tmi_cvm_create(__pa(cvm->params), numa_set); if (!cvm->rd) { - kvm_err("KVM creates cVM: %d\n", cvm->cvm_vmid); + kvm_err("KVM creates cVM failed: %d\n", cvm->cvm_vmid); ret = -ENOMEM; + goto out; }
WRITE_ONCE(cvm->state, CVM_STATE_NEW); @@ -341,7 +342,7 @@ int kvm_cvm_populate_par_region(struct kvm *kvm, u64 numa_set, */ ipa = ALIGN_DOWN(ipa, map_size);
- if (is_data_create_region(ipa_base, args)) { + if (is_data_create_region(ipa, args)) { pfn = gfn_to_pfn_memslot(memslot, gpa_to_gfn(ipa)); if (is_error_pfn(pfn)) { ret = -EFAULT; @@ -602,6 +603,7 @@ static int kvm_populate_ram_region(struct kvm *kvm, u64 map_size, static int kvm_populate_ipa_cvm_range(struct kvm *kvm, struct kvm_cap_arm_tmm_populate_region_args *args) { + struct cvm *cvm = (struct cvm *)kvm->arch.cvm; u64 l2_granule = cvm_granule_size(TMM_TTT_LEVEL_2); phys_addr_t ipa_base1, ipa_end2;
@@ -612,7 +614,10 @@ static int kvm_populate_ipa_cvm_range(struct kvm *kvm, !IS_ALIGNED(args->populate_ipa_base2, PAGE_SIZE) || !IS_ALIGNED(args->populate_ipa_size2, PAGE_SIZE)) return -EINVAL; - if (args->populate_ipa_base2 < args->populate_ipa_base1 + args->populate_ipa_size1) + + if (args->populate_ipa_base1 < cvm->loader_start || + args->populate_ipa_base2 < args->populate_ipa_base1 + args->populate_ipa_size1 || + cvm->dtb_end < args->populate_ipa_base2 + args->populate_ipa_size2) return -EINVAL;
if (args->flags & ~TMI_MEASURE_CONTENT) @@ -755,6 +760,26 @@ int kvm_init_tmm(void) return 0; }
+static bool is_numa_ipa_range_valid(struct kvm_numa_info *numa_info) +{ + unsigned long i; + struct kvm_numa_node *numa_node, *prev_numa_node; + + prev_numa_node = NULL; + for (i = 0; i < numa_info->numa_cnt; i++) { + numa_node = &numa_info->numa_nodes[i]; + if (numa_node->ipa_start + numa_node->ipa_size < numa_node->ipa_start) + return false; + if (prev_numa_node && + numa_node->ipa_start < prev_numa_node->ipa_start + prev_numa_node->ipa_size) + return false; + prev_numa_node = numa_node; + } + if (numa_node->ipa_start + numa_node->ipa_size > CVM_IPA_MAX_VAL) + return false; + return true; +} + int kvm_load_user_data(struct kvm *kvm, unsigned long arg) { struct kvm_user_data user_data; @@ -766,26 +791,34 @@ int kvm_load_user_data(struct kvm *kvm, unsigned long arg) return -EFAULT;
if (copy_from_user(&user_data, argp, sizeof(user_data))) - return -EFAULT; + return -EINVAL;
numa_info = &user_data.numa_info; if (numa_info->numa_cnt > MAX_NUMA_NODE) - return -EFAULT; + return -EINVAL;
if (numa_info->numa_cnt > 0) { unsigned long i, total_size = 0; struct kvm_numa_node *numa_node = &numa_info->numa_nodes[0]; unsigned long ipa_end = numa_node->ipa_start + numa_node->ipa_size;
+ if (!is_numa_ipa_range_valid(numa_info)) + return -EINVAL; if (user_data.loader_start < numa_node->ipa_start || user_data.dtb_end > ipa_end) - return -EFAULT; + return -EINVAL; for (i = 0; i < numa_info->numa_cnt; i++) total_size += numa_info->numa_nodes[i].ipa_size; if (total_size != user_data.ram_size) - return -EFAULT; + return -EINVAL; }
+ if (user_data.image_end <= user_data.loader_start || + user_data.initrd_start < user_data.image_end || + user_data.dtb_end < user_data.initrd_start || + user_data.ram_size < user_data.dtb_end - user_data.loader_start) + return -EINVAL; + cvm->loader_start = user_data.loader_start; cvm->image_end = user_data.image_end; cvm->initrd_start = user_data.initrd_start; @@ -871,6 +904,7 @@ int kvm_init_cvm_vm(struct kvm *kvm) return -ENOMEM;
cvm->params = params; + WRITE_ONCE(cvm->state, CVM_STATE_NONE);
return 0; } diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index 2c2f23f35..153930d01 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2905,7 +2905,7 @@ static void its_free_tables(struct its_node *its) for (i = 0; i < GITS_BASER_NR_REGS; i++) { if (its->tables[i].base) { #ifdef CONFIG_CVM_GUEST - if (!is_cvm_world()) + if (is_cvm_world()) its_free_shared_pages(its->tables[i].base, its->tables[i].order); else
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/8965 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/8965 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/U...