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