All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] KVM: Disable irq while unregistering user notifier
@ 2016-10-21 22:08 Ignacio Alvarado
  2016-11-02 17:25 ` Paolo Bonzini
  0 siblings, 1 reply; 8+ messages in thread
From: Ignacio Alvarado @ 2016-10-21 22:08 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
  Cc: kvm, Radim Krčmář,
	Paolo Bonzini, David Matlack, Ignacio Alvarado

Function user_notifier_unregister should be called only once for each
registered user notifier.

Function kvm_arch_hardware_disable can be executed from an IPI context
which could cause a race condition with a VCPU returning to user mode
and attempting to unregister the notifier.

Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
---
 arch/x86/kvm/x86.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e375235..51f87f0 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -210,7 +210,15 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
 	struct kvm_shared_msrs *locals
 		= container_of(urn, struct kvm_shared_msrs, urn);
 	struct kvm_shared_msr_values *values;
+	unsigned long flags;
 
+	/*
+	 * Disabling irqs at this point since the following code could be
+	 * interrupted and executed through kvm_arch_hardware_disable()
+	 */
+	local_irq_save(flags);
+	if (!locals->registered)
+		goto out;
 	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
 		values = &locals->values[slot];
 		if (values->host != values->curr) {
@@ -220,6 +228,8 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
 	}
 	locals->registered = false;
 	user_return_notifier_unregister(urn);
+out:
+	local_irq_restore(flags);
 }
 
 static void shared_msr_update(unsigned slot, u32 msr)
-- 
2.8.0.rc3.226.g39d4020


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

* Re: [PATCH] KVM: Disable irq while unregistering user notifier
  2016-10-21 22:08 [PATCH] KVM: Disable irq while unregistering user notifier Ignacio Alvarado
@ 2016-11-02 17:25 ` Paolo Bonzini
  2016-11-03 22:26   ` Ignacio Alvarado
  0 siblings, 1 reply; 8+ messages in thread
From: Paolo Bonzini @ 2016-11-02 17:25 UTC (permalink / raw)
  To: Ignacio Alvarado, Thomas Gleixner, Ingo Molnar, H. Peter Anvin
  Cc: kvm, Radim Krčmář, David Matlack



On 22/10/2016 00:08, Ignacio Alvarado wrote:
> Function user_notifier_unregister should be called only once for each
> registered user notifier.
> 
> Function kvm_arch_hardware_disable can be executed from an IPI context
> which could cause a race condition with a VCPU returning to user mode
> and attempting to unregister the notifier.
> 
> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>

Should drop_user_return_notifiers instead be moved to kvm_arch_exit?

Thanks,

Paolo

> ---
>  arch/x86/kvm/x86.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index e375235..51f87f0 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -210,7 +210,15 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>  	struct kvm_shared_msrs *locals
>  		= container_of(urn, struct kvm_shared_msrs, urn);
>  	struct kvm_shared_msr_values *values;
> +	unsigned long flags;
>  
> +	/*
> +	 * Disabling irqs at this point since the following code could be
> +	 * interrupted and executed through kvm_arch_hardware_disable()
> +	 */
> +	local_irq_save(flags);
> +	if (!locals->registered)
> +		goto out;
>  	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
>  		values = &locals->values[slot];
>  		if (values->host != values->curr) {
> @@ -220,6 +228,8 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>  	}
>  	locals->registered = false;
>  	user_return_notifier_unregister(urn);
> +out:
> +	local_irq_restore(flags);
>  }
>  
>  static void shared_msr_update(unsigned slot, u32 msr)
> 

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

* Re: [PATCH] KVM: Disable irq while unregistering user notifier
  2016-11-02 17:25 ` Paolo Bonzini
@ 2016-11-03 22:26   ` Ignacio Alvarado
  2016-11-04  9:48     ` Paolo Bonzini
  0 siblings, 1 reply; 8+ messages in thread
From: Ignacio Alvarado @ 2016-11-03 22:26 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, kvm,
	Radim Krčmář,
	David Matlack

The risk would still be present since fire_user_return_notifiers could
potentially run at any time and kvm_on_user return could be called
from drop_user_return_notifiers either from the kvm_put_kvm path or
the kvm_arch_exit path.

Regards

On Wed, Nov 2, 2016 at 10:25 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 22/10/2016 00:08, Ignacio Alvarado wrote:
>> Function user_notifier_unregister should be called only once for each
>> registered user notifier.
>>
>> Function kvm_arch_hardware_disable can be executed from an IPI context
>> which could cause a race condition with a VCPU returning to user mode
>> and attempting to unregister the notifier.
>>
>> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
>
> Should drop_user_return_notifiers instead be moved to kvm_arch_exit?
>
> Thanks,
>
> Paolo
>
>> ---
>>  arch/x86/kvm/x86.c | 10 ++++++++++
>>  1 file changed, 10 insertions(+)
>>
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index e375235..51f87f0 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -210,7 +210,15 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>       struct kvm_shared_msrs *locals
>>               = container_of(urn, struct kvm_shared_msrs, urn);
>>       struct kvm_shared_msr_values *values;
>> +     unsigned long flags;
>>
>> +     /*
>> +      * Disabling irqs at this point since the following code could be
>> +      * interrupted and executed through kvm_arch_hardware_disable()
>> +      */
>> +     local_irq_save(flags);
>> +     if (!locals->registered)
>> +             goto out;
>>       for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
>>               values = &locals->values[slot];
>>               if (values->host != values->curr) {
>> @@ -220,6 +228,8 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>       }
>>       locals->registered = false;
>>       user_return_notifier_unregister(urn);
>> +out:
>> +     local_irq_restore(flags);
>>  }
>>
>>  static void shared_msr_update(unsigned slot, u32 msr)
>>



-- 
Ignacio Alvarado

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

* Re: [PATCH] KVM: Disable irq while unregistering user notifier
  2016-11-03 22:26   ` Ignacio Alvarado
@ 2016-11-04  9:48     ` Paolo Bonzini
  2016-11-04 18:56       ` Ignacio Alvarado
  0 siblings, 1 reply; 8+ messages in thread
From: Paolo Bonzini @ 2016-11-04  9:48 UTC (permalink / raw)
  To: Ignacio Alvarado
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, kvm,
	Radim Krčmář,
	David Matlack



On 03/11/2016 23:26, Ignacio Alvarado wrote:
> The risk would still be present since fire_user_return_notifiers could
> potentially run at any time and kvm_on_user return could be called
> from drop_user_return_notifiers either from the kvm_put_kvm path or
> the kvm_arch_exit path.

So, do the unregistration

        locals->registered = false;
        user_return_notifier_unregister(urn);

first in kvm_on_user_return?  Nothing else needs to run with IRQs
disabled, and doing it first prevents reentering the code from
kvm_arch_hardware_disable.

Paolo

> Regards
> 
> On Wed, Nov 2, 2016 at 10:25 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>
>>
>> On 22/10/2016 00:08, Ignacio Alvarado wrote:
>>> Function user_notifier_unregister should be called only once for each
>>> registered user notifier.
>>>
>>> Function kvm_arch_hardware_disable can be executed from an IPI context
>>> which could cause a race condition with a VCPU returning to user mode
>>> and attempting to unregister the notifier.
>>>
>>> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
>>
>> Should drop_user_return_notifiers instead be moved to kvm_arch_exit?
>>
>> Thanks,
>>
>> Paolo
>>
>>> ---
>>>  arch/x86/kvm/x86.c | 10 ++++++++++
>>>  1 file changed, 10 insertions(+)
>>>
>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>> index e375235..51f87f0 100644
>>> --- a/arch/x86/kvm/x86.c
>>> +++ b/arch/x86/kvm/x86.c
>>> @@ -210,7 +210,15 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>>       struct kvm_shared_msrs *locals
>>>               = container_of(urn, struct kvm_shared_msrs, urn);
>>>       struct kvm_shared_msr_values *values;
>>> +     unsigned long flags;
>>>
>>> +     /*
>>> +      * Disabling irqs at this point since the following code could be
>>> +      * interrupted and executed through kvm_arch_hardware_disable()
>>> +      */
>>> +     local_irq_save(flags);
>>> +     if (!locals->registered)
>>> +             goto out;
>>>       for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
>>>               values = &locals->values[slot];
>>>               if (values->host != values->curr) {
>>> @@ -220,6 +228,8 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>>       }
>>>       locals->registered = false;
>>>       user_return_notifier_unregister(urn);
>>> +out:
>>> +     local_irq_restore(flags);
>>>  }
>>>
>>>  static void shared_msr_update(unsigned slot, u32 msr)
>>>
> 
> 
> 

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

* Re: [PATCH] KVM: Disable irq while unregistering user notifier
  2016-11-04  9:48     ` Paolo Bonzini
@ 2016-11-04 18:56       ` Ignacio Alvarado
  2016-11-04 19:15         ` [PATCH v2] " Ignacio Alvarado
  0 siblings, 1 reply; 8+ messages in thread
From: Ignacio Alvarado @ 2016-11-04 18:56 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Thomas Gleixner, Ingo Molnar, H. Peter Anvin, kvm,
	Radim Krčmář,
	David Matlack

On Fri, Nov 4, 2016 at 2:48 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>
>
> On 03/11/2016 23:26, Ignacio Alvarado wrote:
>> The risk would still be present since fire_user_return_notifiers could
>> potentially run at any time and kvm_on_user return could be called
>> from drop_user_return_notifiers either from the kvm_put_kvm path or
>> the kvm_arch_exit path.
>
> So, do the unregistration
>
>         locals->registered = false;
>         user_return_notifier_unregister(urn);
>
> first in kvm_on_user_return?  Nothing else needs to run with IRQs
> disabled, and doing it first prevents reentering the code from
> kvm_arch_hardware_disable.
>

Will do.

> Paolo
>
>> Regards
>>
>> On Wed, Nov 2, 2016 at 10:25 AM, Paolo Bonzini <pbonzini@redhat.com> wrote:
>>>
>>>
>>> On 22/10/2016 00:08, Ignacio Alvarado wrote:
>>>> Function user_notifier_unregister should be called only once for each
>>>> registered user notifier.
>>>>
>>>> Function kvm_arch_hardware_disable can be executed from an IPI context
>>>> which could cause a race condition with a VCPU returning to user mode
>>>> and attempting to unregister the notifier.
>>>>
>>>> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
>>>
>>> Should drop_user_return_notifiers instead be moved to kvm_arch_exit?
>>>
>>> Thanks,
>>>
>>> Paolo
>>>
>>>> ---
>>>>  arch/x86/kvm/x86.c | 10 ++++++++++
>>>>  1 file changed, 10 insertions(+)
>>>>
>>>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>>>> index e375235..51f87f0 100644
>>>> --- a/arch/x86/kvm/x86.c
>>>> +++ b/arch/x86/kvm/x86.c
>>>> @@ -210,7 +210,15 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>>>       struct kvm_shared_msrs *locals
>>>>               = container_of(urn, struct kvm_shared_msrs, urn);
>>>>       struct kvm_shared_msr_values *values;
>>>> +     unsigned long flags;
>>>>
>>>> +     /*
>>>> +      * Disabling irqs at this point since the following code could be
>>>> +      * interrupted and executed through kvm_arch_hardware_disable()
>>>> +      */
>>>> +     local_irq_save(flags);
>>>> +     if (!locals->registered)
>>>> +             goto out;
>>>>       for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
>>>>               values = &locals->values[slot];
>>>>               if (values->host != values->curr) {
>>>> @@ -220,6 +228,8 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>>>>       }
>>>>       locals->registered = false;
>>>>       user_return_notifier_unregister(urn);
>>>> +out:
>>>> +     local_irq_restore(flags);
>>>>  }
>>>>
>>>>  static void shared_msr_update(unsigned slot, u32 msr)
>>>>
>>
>>
>>



-- 
Ignacio Alvarado

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

* [PATCH v2] KVM: Disable irq while unregistering user notifier
  2016-11-04 18:56       ` Ignacio Alvarado
@ 2016-11-04 19:15         ` Ignacio Alvarado
  2016-11-17 12:42           ` Paolo Bonzini
  0 siblings, 1 reply; 8+ messages in thread
From: Ignacio Alvarado @ 2016-11-04 19:15 UTC (permalink / raw)
  To: Thomas Gleixner, Ingo Molnar, H. Peter Anvin
  Cc: kvm, Radim Krčmář,
	Paolo Bonzini, David Matlack, Ignacio Alvarado

Function user_notifier_unregister should be called only once for each
registered user notifier.

Function kvm_arch_hardware_disable can be executed from an IPI context
which could cause a race condition with a VCPU returning to user mode
and attempting to unregister the notifier.

Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
---
Changelog since v1:
- Move unregistration to the beginning of kvm_on_user_return

 arch/x86/kvm/x86.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e375235..952e19d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -210,7 +210,18 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
 	struct kvm_shared_msrs *locals
 		= container_of(urn, struct kvm_shared_msrs, urn);
 	struct kvm_shared_msr_values *values;
+	unsigned long flags;
 
+	/*
+	 * Disabling irqs at this point since the following code could be
+	 * interrupted and executed through kvm_arch_hardware_disable()
+	 */
+	local_irq_save(flags);
+	if (locals->registered) {
+		locals->registered = false;
+		user_return_notifier_unregister(urn);
+	}
+	local_irq_restore(flags);
 	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
 		values = &locals->values[slot];
 		if (values->host != values->curr) {
@@ -218,8 +229,6 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
 			values->curr = values->host;
 		}
 	}
-	locals->registered = false;
-	user_return_notifier_unregister(urn);
 }
 
 static void shared_msr_update(unsigned slot, u32 msr)
-- 
2.8.0.rc3.226.g39d4020


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

* Re: [PATCH v2] KVM: Disable irq while unregistering user notifier
  2016-11-04 19:15         ` [PATCH v2] " Ignacio Alvarado
@ 2016-11-17 12:42           ` Paolo Bonzini
  2016-11-19 19:35             ` Radim Krčmář
  0 siblings, 1 reply; 8+ messages in thread
From: Paolo Bonzini @ 2016-11-17 12:42 UTC (permalink / raw)
  To: Ignacio Alvarado, Thomas Gleixner, Ingo Molnar, H. Peter Anvin
  Cc: kvm, Radim Krčmář, David Matlack, stable

On 04/11/2016 20:15, Ignacio Alvarado wrote:
> Function user_notifier_unregister should be called only once for each
> registered user notifier.
> 
> Function kvm_arch_hardware_disable can be executed from an IPI context
> which could cause a race condition with a VCPU returning to user mode
> and attempting to unregister the notifier.
> 
> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>

Cc: stable@vger.kernel.org
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

> ---
> Changelog since v1:
> - Move unregistration to the beginning of kvm_on_user_return
> 
>  arch/x86/kvm/x86.c | 13 +++++++++++--
>  1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index e375235..952e19d 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -210,7 +210,18 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>  	struct kvm_shared_msrs *locals
>  		= container_of(urn, struct kvm_shared_msrs, urn);
>  	struct kvm_shared_msr_values *values;
> +	unsigned long flags;
>  
> +	/*
> +	 * Disabling irqs at this point since the following code could be
> +	 * interrupted and executed through kvm_arch_hardware_disable()
> +	 */
> +	local_irq_save(flags);
> +	if (locals->registered) {
> +		locals->registered = false;
> +		user_return_notifier_unregister(urn);
> +	}
> +	local_irq_restore(flags);
>  	for (slot = 0; slot < shared_msrs_global.nr; ++slot) {
>  		values = &locals->values[slot];
>  		if (values->host != values->curr) {
> @@ -218,8 +229,6 @@ static void kvm_on_user_return(struct user_return_notifier *urn)
>  			values->curr = values->host;
>  		}
>  	}
> -	locals->registered = false;
> -	user_return_notifier_unregister(urn);
>  }
>  
>  static void shared_msr_update(unsigned slot, u32 msr)
> 

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

* Re: [PATCH v2] KVM: Disable irq while unregistering user notifier
  2016-11-17 12:42           ` Paolo Bonzini
@ 2016-11-19 19:35             ` Radim Krčmář
  0 siblings, 0 replies; 8+ messages in thread
From: Radim Krčmář @ 2016-11-19 19:35 UTC (permalink / raw)
  To: Ignacio Alvarado
  Cc: Paolo Bonzini, Thomas Gleixner, Ingo Molnar, H. Peter Anvin, kvm,
	David Matlack, stable

2016-11-17 13:42+0100, Paolo Bonzini:
> On 04/11/2016 20:15, Ignacio Alvarado wrote:
>> Function user_notifier_unregister should be called only once for each
>> registered user notifier.
>> 
>> Function kvm_arch_hardware_disable can be executed from an IPI context
>> which could cause a race condition with a VCPU returning to user mode
>> and attempting to unregister the notifier.
>> 
>> Signed-off-by: Ignacio Alvarado <ikalvarado@google.com>
> 
> Cc: stable@vger.kernel.org
> Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>

Applied to kvm/master, thanks.

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

end of thread, other threads:[~2016-11-19 19:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-10-21 22:08 [PATCH] KVM: Disable irq while unregistering user notifier Ignacio Alvarado
2016-11-02 17:25 ` Paolo Bonzini
2016-11-03 22:26   ` Ignacio Alvarado
2016-11-04  9:48     ` Paolo Bonzini
2016-11-04 18:56       ` Ignacio Alvarado
2016-11-04 19:15         ` [PATCH v2] " Ignacio Alvarado
2016-11-17 12:42           ` Paolo Bonzini
2016-11-19 19:35             ` Radim Krčmář

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.