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]

 



On 03.11.20 14:15, Pavel Machek wrote:
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.

Thanks for noticing!

Greg, do you want me to send the series again or only this patch?


Juergen



@@ -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






[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