linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/2] x86/hyperv: Bug fix and enhancement
@ 2021-11-04 18:22 Sean Christopherson
  2021-11-04 18:22 ` [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails Sean Christopherson
  2021-11-04 18:22 ` [PATCH v2 2/2] x86/hyperv: Move required MSRs check to initial platform probing Sean Christopherson
  0 siblings, 2 replies; 5+ messages in thread
From: Sean Christopherson @ 2021-11-04 18:22 UTC (permalink / raw)
  To: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu, Dexuan Cui
  Cc: linux-hyperv, linux-kernel, Vitaly Kuznetsov, Sean Christopherson

Patch 01 is a fix for a NULL pointer deref that I ran into with a bad VMM
configuration.  That specific error path is remedied by patch 02, but
Hyper-V can still end up in an inactive state if a memory allocation fails.

Patch 02 effectively makes the required MSRs mandatory for recognizing
Hyper-V at all.

Some versions of QEMU prior to ~6.0 make it all too easy to advertise
Hyper-V and a slew of features without advertising the Hyper-V HYPERCALL
MSR, e.g. +hv-ipi,+hv-tlbflush,+hv-vpindex,+hv-reenlightenment advertises
a bunch of things, but not the HYPERCALL MSR.

That results in the guest identifying Hyper-V and setting a variety of PV
ops that then get ignored because hyperv_init() silently disables Hyper-V
for all intents and purposes.  The VMM (or its controller) is obviously
off in the weeds, but ideally the guest kernel would acknowledge the bad
setup in some way.

v2:
  - Add Vitaly's review.
  - Rebase to hyperv-next, commit 285f68afa8b2 ("x86/hyperv: Protect
    set_hv_tscchange_cb() against getting preempted"). [Vitaly]
  - Tweak the changelog in patch 01 to omit the example about a bad VM
    config since the NULL check is needed even if that specific issue is
    resolved.

v1: https://lore.kernel.org/all/20211028222148.2924457-1-seanjc@google.com/t/#u

Sean Christopherson (2):
  x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup
    fails
  x86/hyperv: Move required MSRs check to initial platform probing

 arch/x86/hyperv/hv_init.c      | 12 ++++--------
 arch/x86/kernel/cpu/mshyperv.c | 20 +++++++++++++++-----
 2 files changed, 19 insertions(+), 13 deletions(-)

-- 
2.34.0.rc0.344.g81b53c2807-goog


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
  2021-11-04 18:22 [PATCH v2 0/2] x86/hyperv: Bug fix and enhancement Sean Christopherson
@ 2021-11-04 18:22 ` Sean Christopherson
  2021-11-05 10:16   ` Vitaly Kuznetsov
  2021-11-04 18:22 ` [PATCH v2 2/2] x86/hyperv: Move required MSRs check to initial platform probing Sean Christopherson
  1 sibling, 1 reply; 5+ messages in thread
From: Sean Christopherson @ 2021-11-04 18:22 UTC (permalink / raw)
  To: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu, Dexuan Cui
  Cc: linux-hyperv, linux-kernel, Vitaly Kuznetsov, Sean Christopherson

Check for a valid hv_vp_index array prior to derefencing hv_vp_index when
setting Hyper-V's TSC change callback.  If Hyper-V setup failed in
hyperv_init(), the kernel will still report that it's running under
Hyper-V, but will have silently disabled nearly all functionality.

  BUG: kernel NULL pointer dereference, address: 0000000000000010
  #PF: supervisor read access in kernel mode
  #PF: error_code(0x0000) - not-present page
  PGD 0 P4D 0
  Oops: 0000 [#1] SMP
  CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc2+ #75
  Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
  RIP: 0010:set_hv_tscchange_cb+0x15/0xa0
  Code: <8b> 04 82 8b 15 12 17 85 01 48 c1 e0 20 48 0d ee 00 01 00 f6 c6 08
  ...
  Call Trace:
   kvm_arch_init+0x17c/0x280
   kvm_init+0x31/0x330
   vmx_init+0xba/0x13a
   do_one_initcall+0x41/0x1c0
   kernel_init_freeable+0x1f2/0x23b
   kernel_init+0x16/0x120
   ret_from_fork+0x22/0x30

Fixes: 93286261de1b ("x86/hyperv: Reenlightenment notifications support")
Cc: stable@vger.kernel.org
Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/hyperv/hv_init.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 24f4a06ac46a..7d252a58fbe4 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -177,6 +177,9 @@ void set_hv_tscchange_cb(void (*cb)(void))
 		return;
 	}
 
+	if (!hv_vp_index)
+		return;
+
 	hv_reenlightenment_cb = cb;
 
 	/* Make sure callback is registered before we write to MSRs */
-- 
2.34.0.rc0.344.g81b53c2807-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/2] x86/hyperv: Move required MSRs check to initial platform probing
  2021-11-04 18:22 [PATCH v2 0/2] x86/hyperv: Bug fix and enhancement Sean Christopherson
  2021-11-04 18:22 ` [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails Sean Christopherson
@ 2021-11-04 18:22 ` Sean Christopherson
  1 sibling, 0 replies; 5+ messages in thread
From: Sean Christopherson @ 2021-11-04 18:22 UTC (permalink / raw)
  To: K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu, Dexuan Cui
  Cc: linux-hyperv, linux-kernel, Vitaly Kuznetsov, Sean Christopherson

Explicitly check for MSR_HYPERCALL and MSR_VP_INDEX support when probing
for running as a Hyper-V guest instead of waiting until hyperv_init() to
detect the bogus configuration.  Add messages to give the admin a heads
up that they are likely running on a broken virtual machine setup.

At best, silently disabling Hyper-V is confusing and difficult to debug,
e.g. the kernel _says_ it's using all these fancy Hyper-V features, but
always falls back to the native versions.  At worst, the half baked setup
will crash/hang the kernel.

Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/hyperv/hv_init.c      |  9 +--------
 arch/x86/kernel/cpu/mshyperv.c | 20 +++++++++++++++-----
 2 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 7d252a58fbe4..96eb7db31c8e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -386,20 +386,13 @@ static void __init hv_get_partition_id(void)
  */
 void __init hyperv_init(void)
 {
-	u64 guest_id, required_msrs;
+	u64 guest_id;
 	union hv_x64_msr_hypercall_contents hypercall_msr;
 	int cpuhp;
 
 	if (x86_hyper_type != X86_HYPER_MS_HYPERV)
 		return;
 
-	/* Absolutely required MSRs */
-	required_msrs = HV_MSR_HYPERCALL_AVAILABLE |
-		HV_MSR_VP_INDEX_AVAILABLE;
-
-	if ((ms_hyperv.features & required_msrs) != required_msrs)
-		return;
-
 	if (hv_common_init())
 		return;
 
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 4794b716ec79..ff55df60228f 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -163,12 +163,22 @@ static uint32_t  __init ms_hyperv_platform(void)
 	cpuid(HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS,
 	      &eax, &hyp_signature[0], &hyp_signature[1], &hyp_signature[2]);
 
-	if (eax >= HYPERV_CPUID_MIN &&
-	    eax <= HYPERV_CPUID_MAX &&
-	    !memcmp("Microsoft Hv", hyp_signature, 12))
-		return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
+	if (eax < HYPERV_CPUID_MIN || eax > HYPERV_CPUID_MAX ||
+	    memcmp("Microsoft Hv", hyp_signature, 12))
+		return 0;
 
-	return 0;
+	/* HYPERCALL and VP_INDEX MSRs are mandatory for all features. */
+	eax = cpuid_eax(HYPERV_CPUID_FEATURES);
+	if (!(eax & HV_MSR_HYPERCALL_AVAILABLE)) {
+		pr_warn("x86/hyperv: HYPERCALL MSR not available.\n");
+		return 0;
+	}
+	if (!(eax & HV_MSR_VP_INDEX_AVAILABLE)) {
+		pr_warn("x86/hyperv: VP_INDEX MSR not available.\n");
+		return 0;
+	}
+
+	return HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
 }
 
 static unsigned char hv_get_nmi_reason(void)
-- 
2.34.0.rc0.344.g81b53c2807-goog


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
  2021-11-04 18:22 ` [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails Sean Christopherson
@ 2021-11-05 10:16   ` Vitaly Kuznetsov
  2021-11-08 11:41     ` Wei Liu
  0 siblings, 1 reply; 5+ messages in thread
From: Vitaly Kuznetsov @ 2021-11-05 10:16 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: linux-hyperv, linux-kernel, K. Y. Srinivasan, Haiyang Zhang,
	Stephen Hemminger, Wei Liu, Dexuan Cui

Sean Christopherson <seanjc@google.com> writes:

> Check for a valid hv_vp_index array prior to derefencing hv_vp_index when
> setting Hyper-V's TSC change callback.  If Hyper-V setup failed in
> hyperv_init(), the kernel will still report that it's running under
> Hyper-V, but will have silently disabled nearly all functionality.
>
>   BUG: kernel NULL pointer dereference, address: 0000000000000010
>   #PF: supervisor read access in kernel mode
>   #PF: error_code(0x0000) - not-present page
>   PGD 0 P4D 0
>   Oops: 0000 [#1] SMP
>   CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc2+ #75
>   Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
>   RIP: 0010:set_hv_tscchange_cb+0x15/0xa0
>   Code: <8b> 04 82 8b 15 12 17 85 01 48 c1 e0 20 48 0d ee 00 01 00 f6 c6 08
>   ...
>   Call Trace:
>    kvm_arch_init+0x17c/0x280
>    kvm_init+0x31/0x330
>    vmx_init+0xba/0x13a
>    do_one_initcall+0x41/0x1c0
>    kernel_init_freeable+0x1f2/0x23b
>    kernel_init+0x16/0x120
>    ret_from_fork+0x22/0x30
>
> Fixes: 93286261de1b ("x86/hyperv: Reenlightenment notifications support")
> Cc: stable@vger.kernel.org
> Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  arch/x86/hyperv/hv_init.c | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index 24f4a06ac46a..7d252a58fbe4 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -177,6 +177,9 @@ void set_hv_tscchange_cb(void (*cb)(void))
>  		return;
>  	}
>  
> +	if (!hv_vp_index)
> +		return;
> +

Arguably, we could've merged this with 'if (!hv_reenlightenment_available())' 
above to get a message printed:

diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index 24f4a06ac46a..4a2a091c2f0e 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -172,7 +172,7 @@ void set_hv_tscchange_cb(void (*cb)(void))
        };
        struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
 
-       if (!hv_reenlightenment_available()) {
+       if (!hv_reenlightenment_available() || !hv_vp_index) {
                pr_warn("Hyper-V: reenlightenment support is unavailable\n");
                return;
        }

just to have an indication that something is off.

>  	hv_reenlightenment_cb = cb;
>  
>  	/* Make sure callback is registered before we write to MSRs */

With or without the change,

Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>

-- 
Vitaly


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails
  2021-11-05 10:16   ` Vitaly Kuznetsov
@ 2021-11-08 11:41     ` Wei Liu
  0 siblings, 0 replies; 5+ messages in thread
From: Wei Liu @ 2021-11-08 11:41 UTC (permalink / raw)
  To: Vitaly Kuznetsov
  Cc: Sean Christopherson, linux-hyperv, linux-kernel,
	K. Y. Srinivasan, Haiyang Zhang, Stephen Hemminger, Wei Liu,
	Dexuan Cui

On Fri, Nov 05, 2021 at 11:16:14AM +0100, Vitaly Kuznetsov wrote:
> Sean Christopherson <seanjc@google.com> writes:
> 
> > Check for a valid hv_vp_index array prior to derefencing hv_vp_index when
> > setting Hyper-V's TSC change callback.  If Hyper-V setup failed in
> > hyperv_init(), the kernel will still report that it's running under
> > Hyper-V, but will have silently disabled nearly all functionality.
> >
> >   BUG: kernel NULL pointer dereference, address: 0000000000000010
> >   #PF: supervisor read access in kernel mode
> >   #PF: error_code(0x0000) - not-present page
> >   PGD 0 P4D 0
> >   Oops: 0000 [#1] SMP
> >   CPU: 4 PID: 1 Comm: swapper/0 Not tainted 5.15.0-rc2+ #75
> >   Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
> >   RIP: 0010:set_hv_tscchange_cb+0x15/0xa0
> >   Code: <8b> 04 82 8b 15 12 17 85 01 48 c1 e0 20 48 0d ee 00 01 00 f6 c6 08
> >   ...
> >   Call Trace:
> >    kvm_arch_init+0x17c/0x280
> >    kvm_init+0x31/0x330
> >    vmx_init+0xba/0x13a
> >    do_one_initcall+0x41/0x1c0
> >    kernel_init_freeable+0x1f2/0x23b
> >    kernel_init+0x16/0x120
> >    ret_from_fork+0x22/0x30
> >
> > Fixes: 93286261de1b ("x86/hyperv: Reenlightenment notifications support")
> > Cc: stable@vger.kernel.org
> > Cc: Vitaly Kuznetsov <vkuznets@redhat.com>
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> >  arch/x86/hyperv/hv_init.c | 3 +++
> >  1 file changed, 3 insertions(+)
> >
> > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> > index 24f4a06ac46a..7d252a58fbe4 100644
> > --- a/arch/x86/hyperv/hv_init.c
> > +++ b/arch/x86/hyperv/hv_init.c
> > @@ -177,6 +177,9 @@ void set_hv_tscchange_cb(void (*cb)(void))
> >  		return;
> >  	}
> >  
> > +	if (!hv_vp_index)
> > +		return;
> > +
> 
> Arguably, we could've merged this with 'if (!hv_reenlightenment_available())' 
> above to get a message printed:
> 
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index 24f4a06ac46a..4a2a091c2f0e 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -172,7 +172,7 @@ void set_hv_tscchange_cb(void (*cb)(void))
>         };
>         struct hv_tsc_emulation_control emu_ctrl = {.enabled = 1};
>  
> -       if (!hv_reenlightenment_available()) {
> +       if (!hv_reenlightenment_available() || !hv_vp_index) {
>                 pr_warn("Hyper-V: reenlightenment support is unavailable\n");
>                 return;
>         }
> 
> just to have an indication that something is off.
> 
> >  	hv_reenlightenment_cb = cb;
> >  
> >  	/* Make sure callback is registered before we write to MSRs */
> 
> With or without the change,
> 
> Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com>

Thanks Sean and Vitaly. Both patches look good to me. They will be taken
via hyperv-fixes after v5.16-rc1 is cut.

Wei.

> 
> -- 
> Vitaly
> 

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-11-08 11:41 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-04 18:22 [PATCH v2 0/2] x86/hyperv: Bug fix and enhancement Sean Christopherson
2021-11-04 18:22 ` [PATCH v2 1/2] x86/hyperv: Fix NULL deref in set_hv_tscchange_cb() if Hyper-V setup fails Sean Christopherson
2021-11-05 10:16   ` Vitaly Kuznetsov
2021-11-08 11:41     ` Wei Liu
2021-11-04 18:22 ` [PATCH v2 2/2] x86/hyperv: Move required MSRs check to initial platform probing Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).