Re: [PATCH 02/13] xen/events: avoid removing an event channel while handling it

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi!

> Today it can happen that an event channel is being removed from the
> system while the event handling loop is active. This can lead to a
> race resulting in crashes or WARN() splats when trying to access the
> irq_info structure related to the event channel.
> 
> Fix this problem by using a rwlock taken as reader in the event
> handling loop and as writer when deallocating the irq_info structure.
> 
> As the observed problem was a NULL dereference in evtchn_from_irq()
> make this function more robust against races by testing the irq_info
> pointer to be not NULL before dereferencing it.
> 
> And finally make all accesses to evtchn_to_irq[row][col] atomic ones
> in order to avoid seeing partial updates of an array element in irq
> handling. Note that irq handling can be entered only for event channels
> which have been valid before, so any not populated row isn't a problem
> in this regard, as rows are only ever added and never removed.
> 
> This is XSA-331.
> 
> This is upstream commit 073d0552ead5bfc7a3a9c01de590e924f11b5dd2

This one is mismerged.


> @@ -1242,6 +1269,8 @@ static void __xen_evtchn_do_upcall(void)
>  	int cpu = get_cpu();
>  	unsigned count;
>  
> +	read_lock(&evtchn_rwlock);
> +
>  	do {
>  		vcpu_info->evtchn_upcall_pending = 0;
>  
> @@ -1256,6 +1285,8 @@ static void __xen_evtchn_do_upcall(void)
>  		__this_cpu_write(xed_nesting_count, 0);
>  	} while (count != 1 || vcpu_info->evtchn_upcall_pending);
>  
> +	read_unlock(&evtchn_rwlock);
> +
>  out:

read_unlock needs to be after the out: label. Or better yet, goto can
be avoided.

Best regards,
								Pavel
Signed-off-by: Pavel Machek (CIP) <pavel@xxxxxxx>

diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index cef70f4b52ef..ba36bdd49d22 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -1556,8 +1556,8 @@ static void __xen_evtchn_do_upcall(void)
 	do {
 		vcpu_info->evtchn_upcall_pending = 0;
 
-		if (__this_cpu_inc_return(xed_nesting_count) - 1)
-			goto out;
+		if (__this_cpu_inc_return(xed_nesting_count) != 1)
+			break;
 
 		xen_evtchn_handle_events(cpu, &ctrl);
 
@@ -1568,8 +1568,6 @@ static void __xen_evtchn_do_upcall(void)
 	} while (count != 1 || vcpu_info->evtchn_upcall_pending);
 
 	read_unlock(&evtchn_rwlock);
-
-out:
 	/*
 	 * Increment irq_epoch only now to defer EOIs only for
 	 * xen_irq_lateeoi() invocations occurring from inside the loop


-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux