Skip to content

Commit 057bed2

Browse files
willdeaconMarc Zyngier
authored andcommitted
KVM: arm64: Disable privileged hypercalls after pKVM finalisation
After pKVM has been 'finalised' using the __pkvm_prot_finalize hypercall, the calling CPU will have a Stage-2 translation enabled to prevent access to memory pages owned by EL2. Although this forms a significant part of the process to deprivilege the host kernel, we also need to ensure that the hypercall interface is reduced so that the EL2 code cannot, for example, be re-initialised using a new set of vectors. Re-order the hypercalls so that only a suffix remains available after finalisation of pKVM. Cc: Marc Zyngier <[email protected]> Cc: Quentin Perret <[email protected]> Signed-off-by: Will Deacon <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 07036cf commit 057bed2

File tree

2 files changed

+40
-22
lines changed

2 files changed

+40
-22
lines changed

arch/arm64/include/asm/kvm_asm.h

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -50,27 +50,30 @@
5050
#include <linux/mm.h>
5151

5252
enum __kvm_host_smccc_func {
53+
/* Hypercalls available only prior to pKVM finalisation */
5354
/* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */
54-
__KVM_HOST_SMCCC_FUNC___kvm_vcpu_run = __KVM_HOST_SMCCC_FUNC___kvm_hyp_init + 1,
55+
__KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2 = __KVM_HOST_SMCCC_FUNC___kvm_hyp_init + 1,
56+
__KVM_HOST_SMCCC_FUNC___pkvm_init,
57+
__KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping,
58+
__KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector,
59+
__KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs,
60+
__KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs,
61+
__KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config,
62+
__KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,
63+
64+
/* Hypercalls available after pKVM finalisation */
65+
__KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp,
66+
__KVM_HOST_SMCCC_FUNC___kvm_adjust_pc,
67+
__KVM_HOST_SMCCC_FUNC___kvm_vcpu_run,
5568
__KVM_HOST_SMCCC_FUNC___kvm_flush_vm_context,
5669
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_ipa,
5770
__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid,
5871
__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
5972
__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
60-
__KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs,
61-
__KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config,
6273
__KVM_HOST_SMCCC_FUNC___vgic_v3_read_vmcr,
6374
__KVM_HOST_SMCCC_FUNC___vgic_v3_write_vmcr,
64-
__KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs,
65-
__KVM_HOST_SMCCC_FUNC___kvm_get_mdcr_el2,
6675
__KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs,
6776
__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_aprs,
68-
__KVM_HOST_SMCCC_FUNC___pkvm_init,
69-
__KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp,
70-
__KVM_HOST_SMCCC_FUNC___pkvm_create_private_mapping,
71-
__KVM_HOST_SMCCC_FUNC___pkvm_cpu_set_vector,
72-
__KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,
73-
__KVM_HOST_SMCCC_FUNC___kvm_adjust_pc,
7477
};
7578

7679
#define DECLARE_KVM_VHE_SYM(sym) extern char sym[]

arch/arm64/kvm/hyp/nvhe/hyp-main.c

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -165,36 +165,51 @@ typedef void (*hcall_t)(struct kvm_cpu_context *);
165165
#define HANDLE_FUNC(x) [__KVM_HOST_SMCCC_FUNC_##x] = (hcall_t)handle_##x
166166

167167
static const hcall_t host_hcall[] = {
168-
HANDLE_FUNC(__kvm_vcpu_run),
168+
/* ___kvm_hyp_init */
169+
HANDLE_FUNC(__kvm_get_mdcr_el2),
170+
HANDLE_FUNC(__pkvm_init),
171+
HANDLE_FUNC(__pkvm_create_private_mapping),
172+
HANDLE_FUNC(__pkvm_cpu_set_vector),
173+
HANDLE_FUNC(__kvm_enable_ssbs),
174+
HANDLE_FUNC(__vgic_v3_init_lrs),
175+
HANDLE_FUNC(__vgic_v3_get_gic_config),
176+
HANDLE_FUNC(__pkvm_prot_finalize),
177+
178+
HANDLE_FUNC(__pkvm_host_share_hyp),
169179
HANDLE_FUNC(__kvm_adjust_pc),
180+
HANDLE_FUNC(__kvm_vcpu_run),
170181
HANDLE_FUNC(__kvm_flush_vm_context),
171182
HANDLE_FUNC(__kvm_tlb_flush_vmid_ipa),
172183
HANDLE_FUNC(__kvm_tlb_flush_vmid),
173184
HANDLE_FUNC(__kvm_flush_cpu_context),
174185
HANDLE_FUNC(__kvm_timer_set_cntvoff),
175-
HANDLE_FUNC(__kvm_enable_ssbs),
176-
HANDLE_FUNC(__vgic_v3_get_gic_config),
177186
HANDLE_FUNC(__vgic_v3_read_vmcr),
178187
HANDLE_FUNC(__vgic_v3_write_vmcr),
179-
HANDLE_FUNC(__vgic_v3_init_lrs),
180-
HANDLE_FUNC(__kvm_get_mdcr_el2),
181188
HANDLE_FUNC(__vgic_v3_save_aprs),
182189
HANDLE_FUNC(__vgic_v3_restore_aprs),
183-
HANDLE_FUNC(__pkvm_init),
184-
HANDLE_FUNC(__pkvm_cpu_set_vector),
185-
HANDLE_FUNC(__pkvm_host_share_hyp),
186-
HANDLE_FUNC(__pkvm_create_private_mapping),
187-
HANDLE_FUNC(__pkvm_prot_finalize),
188190
};
189191

190192
static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
191193
{
192194
DECLARE_REG(unsigned long, id, host_ctxt, 0);
195+
unsigned long hcall_min = 0;
193196
hcall_t hfn;
194197

198+
/*
199+
* If pKVM has been initialised then reject any calls to the
200+
* early "privileged" hypercalls. Note that we cannot reject
201+
* calls to __pkvm_prot_finalize for two reasons: (1) The static
202+
* key used to determine initialisation must be toggled prior to
203+
* finalisation and (2) finalisation is performed on a per-CPU
204+
* basis. This is all fine, however, since __pkvm_prot_finalize
205+
* returns -EPERM after the first call for a given CPU.
206+
*/
207+
if (static_branch_unlikely(&kvm_protected_mode_initialized))
208+
hcall_min = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize;
209+
195210
id -= KVM_HOST_SMCCC_ID(0);
196211

197-
if (unlikely(id >= ARRAY_SIZE(host_hcall)))
212+
if (unlikely(id < hcall_min || id >= ARRAY_SIZE(host_hcall)))
198213
goto inval;
199214

200215
hfn = host_hcall[id];

0 commit comments

Comments
 (0)