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

Re: [PATCH 1/2] xen/sched: core: skip missing vcpu slots in sched_move_domain()


  • To: Jürgen Groß <jgross@xxxxxxxx>, Furkan Çalışkan <frn1furkan10@xxxxxxxxx>, xen-devel@xxxxxxxxxxxxxxxxxxxx
  • From: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
  • Date: Tue, 18 Aug 2026 11:35:13 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=a72T3B3V1OW7tNrgOO/ktM4/K+rzTKrQksiFPMT06IQ=; b=a49W2RA9hOEloL2DQ2dRSfsnqK507g57XRK4Bu79/PSlOq84ODp0h+YjRECdgsuiN0bRE56fgeif+DChV+lX0aCFvPoNwiM3Yjz9g7Kdg9OLA+xJkcn/pU1ueSsXj1dx/af60pmJKhJJ00QbDB7oAkwOL9zGLw0P32sDxP9fVoazoN8RVsxUGuWf96dTLyic3ZbK9gbYNRKZnHl+UHhIXrYmrSmQVwExoqYnFxALvMMU4DSP3LNTiY7mU5hQxJqgizqfqokMzXKkiWwIRW6HMqnksqeOdYQuiqJzo6TR3B0I1lFaFMm2qoyxTJQ1xk4ZLnJeEI/sLLLtqFKPSUb9/w==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=mJD9W62zqW029P5LaJ9kR2gzvxyUg7J9z/ingio94S2WpZ72VNToStfG9Jjh5WJQwqdqcTZPrIK+cEuBilh8Y9uIQ+V/i/Vxcf/JCHZYNXqkbKewFQgwz/NHxnLCa47tigqkjbT0mD5kbNGQ5xxhkC6GbyxsLQb20HvobFzh/vbIuOlg86+BlMIfwjkUH1GhpgPNGqnYZnGNevOLravgFsbVu2o+8HThOXpd3+joco9RNIqJB8RW/Akkz80RBPSLswbSFJOj1qbsVbeP/gY5JaAs8Koy2I1b40M9kh+b6U93qQMbs2PlV2hkdBLnqG0pfJ3ckVo9ymI6BsVXuJhdfg==
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=citrix.com header.i="@citrix.com" header.h="From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck"
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Autocrypt: addr=andrew.cooper3@xxxxxxxxxx; keydata= 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 6+ahAA==
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, jbeulich@xxxxxxxx, dfaggioli@xxxxxxxx, gwd@xxxxxxxxxxxxxx
  • Delivery-date: Tue, 18 Aug 2026 10:35:29 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

On 18/08/2026 11:13 am, Jürgen Groß wrote:
> On 18.08.26 12:04, Andrew Cooper wrote:
>> On 18/08/2026 8:53 am, Furkan Çalışkan wrote:
>>> On 8/18/26 10:11, Jürgen Groß wrote:
>>>> On 18.08.26 08:32, Furkan Caliskan wrote:
>>>>> sched_move_domain() derives the number of units to rebuild from
>>>>> d->max_vcpus, which is fixed at domain creation and never rolled
>>>>> back if vcpu_create() fails partway through building a domain. So
>>>>> d->vcpu[i] can be NULL for some i even though max_vcpus still
>>>>> counts it - this happens if sched_alloc_udata() returns NULL.
>>>>>
>>>>> The per-unit loop doesn't check for this: it sets
>>>>> unit->vcpu_list = d->vcpu[unit_id] (NULL) and hands that broken
>>>>> unit straight to the destination scheduler's alloc_udata(),
>>>>> which assumes vcpu_list is always valid and crashes Xen when
>>>>> it is not.
>>>>>
>>>>> Reproduced by building a domain in a non-default cpupool where
>>>>> vcpu creation fails partway through, then destroying it.
>>>>> domain_kill() moves the domain back to the default cpupool via
>>>>> sched_move_domain() before actually destroying it, crashing
>>>>> inside the destination scheduler's alloc_udata() (seen in
>>>>> Credit2's csched2_alloc_udata() -> is_idle_unit() -> NULL deref).
>>>>>
>>>>> Before building a unit in sched_move_domain(), check that all of
>>>>> its vcpu slots are populated, and skip it if any are missing. The
>>>>> rest of the function walks the vcpus that actually exist, via
>>>>> for_each_vcpu() rather than n_units, so skipping a unit here
>>>>> does not leave anything else out of sync.
>>>>>
>>>>> Signed-off-by: Furkan Caliskan <frn1furkan10@xxxxxxxxx>
>>>>> ---
>>>>>    xen/common/sched/core.c | 19 +++++++++++++++++++
>>>>>    1 file changed, 19 insertions(+)
>>>>>
>>>>> diff --git a/xen/common/sched/core.c b/xen/common/sched/core.c
>>>>> index d3a0a97e1d..d542c76543 100644
>>>>> --- a/xen/common/sched/core.c
>>>>> +++ b/xen/common/sched/core.c
>>>>> @@ -745,6 +745,25 @@ int sched_move_domain(struct domain *d,
>>>>> struct cpupool *c)
>>>>>          for ( unit_idx = 0; unit_idx < n_units; unit_idx++ )
>>>>>        {
>>>>> +        /*
>>>>> +         * Skip this unit if any of its vcpus is missing. Bounded by
>>>>> +         * max_vcpus.
>>>>> +         */
>>>>> +        bool vcpu_failed = false;
>>>>> +
>>>>> +        for ( unsigned int i = 0;
>>>>> +              i < gran && unit_idx * gran + i < d->max_vcpus; i++ )
>>>>> +        {
>>>>> +            if ( !d->vcpu[unit_idx * gran + i] )
>>>>> +            {
>>>>> +                vcpu_failed = true;
>>>>> +                break;
>>>>> +            }
>>>>> +        }
>>>>> +
>>>>> +        if ( vcpu_failed )
>>>>> +            continue;
>>>> I don't think this is correct.
>>>>
>>>> If there are some vcpus in the unit you will loose them (i.e. make
>>>> them no
>>>> longer be able to be scheduled), right?
>>>>
>>>> For a dying domain this might be okay, but not for one still
>>>> active. So I think
>>>> you should at least verify the domain is dying, otherwise
>>>> sched_move_domain()
>>>> should just fail.
>>>>
>>>> An alternative might be to fix the NULL dereferencing where needed,
>>>> but this
>>>> could become tedious.
>>>>
>>>>
>>>> Juergen
>>> Right. My initial attempt only checked 'd->vcpu[unit_idx*gran]'
>>> for the head vCPU. The crash happens when unit->vcpu_list is set
>>> to d->vcpu[unit_idx*gran] (which is NULL) and passed to
>>> 'alloc_udata()',
>>> causing a NULL dereference.
>>>
>>> I expanded the loop over 'gran' to handle core-scheduling cases where a
>>> subsequent vCPU fails mid-unit, but as you pointed out, that drops the
>>> whole unit for active domain.
>>>
>>> I'll update the patch to check d->is_dying to skip incomplete units
>>> only for dying domains, and have sched_move_domain() fail if an active
>>> domain has missing vCPUs
>>
>> I'm afraid that wont fix everything.
>
> Why not?

domU's in this situation do not have is_dying set.

~Andrew



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.