diff mbox series

[1/5] arm64: Prevent kexec and hibernation if is_protected_kvm_enabled()

Message ID 20210923112256.15767-2-will@kernel.org (mailing list archive)
State New, archived
Headers show
Series KVM: arm64: Restrict host hypercalls when pKVM is enabled | expand

Commit Message

Will Deacon Sept. 23, 2021, 11:22 a.m. UTC
When pKVM is enabled, the hypervisor code at EL2 and its data structures
are inaccessible to the host kernel and cannot be torn down or replaced
as this would defeat the integrity properies which pKVM aims to provide.
Furthermore, the ABI between the host and EL2 is flexible and private to
whatever the current implementation of KVM requires and so booting a new
kernel with an old EL2 component is very likely to end in disaster.

In preparation for uninstalling the hyp stub calls which are relied upon
to reset EL2, disable kexec and hibernation in the host when protected
KVM is enabled.

Cc: Marc Zyngier <maz@kernel.org>
Cc: Quentin Perret <qperret@google.com>
Signed-off-by: Will Deacon <will@kernel.org>
---
 arch/arm64/kernel/smp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Mark Rutland Sept. 23, 2021, 11:45 a.m. UTC | #1
On Thu, Sep 23, 2021 at 12:22:52PM +0100, Will Deacon wrote:
> When pKVM is enabled, the hypervisor code at EL2 and its data structures
> are inaccessible to the host kernel and cannot be torn down or replaced
> as this would defeat the integrity properies which pKVM aims to provide.
> Furthermore, the ABI between the host and EL2 is flexible and private to
> whatever the current implementation of KVM requires and so booting a new
> kernel with an old EL2 component is very likely to end in disaster.
> 
> In preparation for uninstalling the hyp stub calls which are relied upon
> to reset EL2, disable kexec and hibernation in the host when protected
> KVM is enabled.
> 
> Cc: Marc Zyngier <maz@kernel.org>
> Cc: Quentin Perret <qperret@google.com>
> Signed-off-by: Will Deacon <will@kernel.org>
> ---
>  arch/arm64/kernel/smp.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 6f6ff072acbd..44369b99a57e 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -1128,5 +1128,6 @@ bool cpus_are_stuck_in_kernel(void)
>  {
>  	bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
>  
> -	return !!cpus_stuck_in_kernel || smp_spin_tables;
> +	return !!cpus_stuck_in_kernel || smp_spin_tables ||
> +		is_protected_kvm_enabled();
>  }

IIUC you'll also need to do something to prevent kdump, since even with
CPUs stuck in the kernel that will try to do a kexec on the crashed CPU
and __cpu_soft_restart() won't be able to return to EL2.

You could fiddle with the BUG_ON() in machine_kexec() to die in this
case too.

Thanks,
Mark.

> -- 
> 2.33.0.464.g1972c5931b-goog
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
Will Deacon Sept. 23, 2021, 12:29 p.m. UTC | #2
On Thu, Sep 23, 2021 at 12:45:06PM +0100, Mark Rutland wrote:
> On Thu, Sep 23, 2021 at 12:22:52PM +0100, Will Deacon wrote:
> > When pKVM is enabled, the hypervisor code at EL2 and its data structures
> > are inaccessible to the host kernel and cannot be torn down or replaced
> > as this would defeat the integrity properies which pKVM aims to provide.
> > Furthermore, the ABI between the host and EL2 is flexible and private to
> > whatever the current implementation of KVM requires and so booting a new
> > kernel with an old EL2 component is very likely to end in disaster.
> > 
> > In preparation for uninstalling the hyp stub calls which are relied upon
> > to reset EL2, disable kexec and hibernation in the host when protected
> > KVM is enabled.
> > 
> > Cc: Marc Zyngier <maz@kernel.org>
> > Cc: Quentin Perret <qperret@google.com>
> > Signed-off-by: Will Deacon <will@kernel.org>
> > ---
> >  arch/arm64/kernel/smp.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> > 
> > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> > index 6f6ff072acbd..44369b99a57e 100644
> > --- a/arch/arm64/kernel/smp.c
> > +++ b/arch/arm64/kernel/smp.c
> > @@ -1128,5 +1128,6 @@ bool cpus_are_stuck_in_kernel(void)
> >  {
> >  	bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
> >  
> > -	return !!cpus_stuck_in_kernel || smp_spin_tables;
> > +	return !!cpus_stuck_in_kernel || smp_spin_tables ||
> > +		is_protected_kvm_enabled();
> >  }
> 
> IIUC you'll also need to do something to prevent kdump, since even with
> CPUs stuck in the kernel that will try to do a kexec on the crashed CPU
> and __cpu_soft_restart() won't be able to return to EL2.
> 
> You could fiddle with the BUG_ON() in machine_kexec() to die in this
> case too.

I wondered about that, and I'm happy to do it if you reckon it's better,
but if the host is crashing _anyway_ then I wasn't convinced it was worth
the effort. With the approach here, we'll WARN and then enter the kdump
kernel at EL1 which maybe might work sometimes possibly? I suppose if the
kdump kernel is careful about the memory it accesses, then it has a
fighting chance of doing something useful.

Will
diff mbox series

Patch

diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 6f6ff072acbd..44369b99a57e 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -1128,5 +1128,6 @@  bool cpus_are_stuck_in_kernel(void)
 {
 	bool smp_spin_tables = (num_possible_cpus() > 1 && !have_cpu_die());
 
-	return !!cpus_stuck_in_kernel || smp_spin_tables;
+	return !!cpus_stuck_in_kernel || smp_spin_tables ||
+		is_protected_kvm_enabled();
 }