From: Stewart Hildebrand Date: Tue, 23 May 2023 12:56:04 +0000 (+0200) Subject: sched/null: avoid crash after failed domU creation X-Git-Tag: RELEASE-4.17.2~71 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=8a13397211b6f6495d095f1214ed122db8f2081d;p=xen.git sched/null: avoid crash after failed domU creation When creating a domU, but the creation fails, there is a corner case that may lead to a crash in the null scheduler when running a debug build of Xen. (XEN) **************************************** (XEN) Panic on CPU 0: (XEN) Assertion 'npc->unit == unit' failed at common/sched/null.c:379 (XEN) **************************************** The events leading to the crash are: * null_unit_insert() was invoked with the unit offline. Since the unit was offline, unit_assign() was not called, and null_unit_insert() returned. * Later during domain creation, the unit was onlined * Eventually, domain creation failed due to bad configuration * null_unit_remove() was invoked with the unit still online. Since the unit was online, it called unit_deassign() and triggered an ASSERT. To fix this, only call unit_deassign() when npc->unit is non-NULL in null_unit_remove. Signed-off-by: Stewart Hildebrand Reviewed-by: Juergen Gross Acked-by: Dario Faggioli master commit: c2eae2614c8f04e384cd3334c3f06f31a6cb5f41 master date: 2023-05-22 16:11:40 +0200 --- diff --git a/xen/common/sched/null.c b/xen/common/sched/null.c index 65a0a6c531..2091337fcd 100644 --- a/xen/common/sched/null.c +++ b/xen/common/sched/null.c @@ -522,6 +522,8 @@ static void cf_check null_unit_remove( { struct null_private *prv = null_priv(ops); struct null_unit *nvc = null_unit(unit); + struct null_pcpu *npc; + unsigned int cpu; spinlock_t *lock; ASSERT(!is_idle_unit(unit)); @@ -531,8 +533,6 @@ static void cf_check null_unit_remove( /* If offline, the unit shouldn't be assigned, nor in the waitqueue */ if ( unlikely(!is_unit_online(unit)) ) { - struct null_pcpu *npc; - npc = unit->res->sched_priv; ASSERT(npc->unit != unit); ASSERT(list_empty(&nvc->waitq_elem)); @@ -549,7 +549,10 @@ static void cf_check null_unit_remove( goto out; } - unit_deassign(prv, unit); + cpu = sched_unit_master(unit); + npc = get_sched_res(cpu)->sched_priv; + if ( npc->unit ) + unit_deassign(prv, unit); out: unit_schedule_unlock_irq(lock, unit);