ANDROID: KVM: arm64: Move pKVM host deprivilege to device_initcall

In preparation for early loading of pKVM modules (i.e. before
deprivilege), move the pKVM finalization in device_initcall. This is
needed as modules are found in the initramfs whom unpack starts in the
previous initcall.

A deprivilege failure now ends-up in erasing the PVM firmware and simply
prevent loading of any protected VM.

As an interesting side effect, it also allows us to mark the module
loading functions as __init.  Those functions will then be erased once
the init is complete, reducing the attack surface.

Bug: 254835242
Change-Id: Ifab4b9167b8924222bc8b6c2a0af529a3f8540c0
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
This commit is contained in:
Vincent Donnefort
2022-11-29 14:34:55 +00:00
parent 8a87989900
commit 408fad8bb6
2 changed files with 27 additions and 22 deletions

View File

@@ -2271,20 +2271,6 @@ static int pkvm_drop_host_privileges(void)
return ret;
}
static int finalize_hyp_mode(void)
{
if (!is_protected_kvm_enabled())
return 0;
/*
* Exclude HYP sections from kmemleak so that they don't get peeked
* at, which would end badly once inaccessible.
*/
kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start);
kmemleak_free_part_phys(hyp_mem_base, hyp_mem_size);
return pkvm_drop_host_privileges();
}
struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
{
struct kvm_vcpu *vcpu;
@@ -2400,12 +2386,6 @@ int kvm_arch_init(void *opaque)
goto out_hyp;
if (!in_hyp_mode) {
err = finalize_hyp_mode();
if (err) {
kvm_err("Failed to finalize Hyp protection\n");
goto out_hyp;
}
err = init_hyp_tracefs();
if (err)
kvm_err("Failed to initialize Hyp tracing\n");

View File

@@ -433,7 +433,7 @@ static int __init pkvm_firmware_rmem_clear(void)
void *addr;
phys_addr_t size;
if (likely(!pkvm_firmware_mem) || is_protected_kvm_enabled())
if (likely(!pkvm_firmware_mem))
return 0;
kvm_info("Clearing unused pKVM firmware memory\n");
@@ -447,7 +447,32 @@ static int __init pkvm_firmware_rmem_clear(void)
memunmap(addr);
return 0;
}
device_initcall_sync(pkvm_firmware_rmem_clear);
static int __init finalize_pkvm(void)
{
int ret;
if (!is_protected_kvm_enabled()) {
pkvm_firmware_rmem_clear();
return 0;
}
/*
* Exclude HYP sections from kmemleak so that they don't get peeked
* at, which would end badly once inaccessible.
*/
kmemleak_free_part(__hyp_bss_start, __hyp_bss_end - __hyp_bss_start);
kmemleak_free_part_phys(hyp_mem_base, hyp_mem_size);
ret = pkvm_drop_host_privileges();
if (ret) {
pr_err("Failed to de-privilege the host kernel: %d\n", ret);
pkvm_firmware_rmem_clear();
}
return ret;
}
device_initcall_sync(finalize_pkvm);
static int pkvm_vm_ioctl_set_fw_ipa(struct kvm *kvm, u64 ipa)
{