Re: [PATCH v3 1/2] xen/common: add vcpus_create() and keep max_vcpus in sync
Jürgen Groß <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <[email protected]> |
On 31.08.26 07:16, Furkan Caliskan wrote:
> Every vcpu_create() call site that builds more than one vcpu loops
> over ids up to d->max_vcpus and stops on the first failure, but none
> of them roll max_vcpus back to match. This leaves d->vcpu[i] == NULL
> for ids below max_vcpus, which anything walking d->vcpu[] can then
> dereference. This is what caused the crash: sched_move_domain()
> walks every vcpu slot up to max_vcpus without checking for empty
> ones, so when a domain built in a non-default cpupool had vcpu
> creation fail partway through, domain_kill() later moving it back
> to the default cpupool handed one of its empty slots straight to
> the new cpupool's scheduler, causing a NULL-pointer dereference
> inside sched_alloc_udata().
>
> Add vcpus_create(d): creates every vcpu of d up to max_vcpus and
> rolls max_vcpus back to the failed id on error. This keeps
> d->vcpu[i] is non-NULL for all i < d->max_vcpus, instead of guarding
> every reader of d->vcpu[] agains holes individually.
>
> Convert every site that builds vcpus in a loop to call this function
> instead.
>
> Fixes: 61649709421a ("xen/domain: Allocate d->vcpu[] in domain_create()")
> Suggested-by: Juergen Gross <[email protected]>
> Signed-off-by: Furkan Caliskan <[email protected]>
> ---
> v3:
> - Reworked per Juergen's suggestion: instead of guarding
> sched_move_domain() against a missing vcpu slot, keep d->max_vcpus
> in sync with the vcpus actually created. Added vcpus_create() and
> converted every vcpu_create() loop to use it.
> - Reverted the sched_move_domain() check from v2, now unneeded.
> ---
> xen/arch/arm/domain_build.c | 15 +++++++--------
> xen/arch/x86/mm/mem_sharing.c | 11 ++---------
> xen/common/domain.c | 24 ++++++++++++++++++++++++
> xen/common/domctl.c | 19 ++++---------------
> xen/common/sched/core.c | 7 +++----
> xen/include/xen/domain.h | 1 +
> 6 files changed, 41 insertions(+), 36 deletions(-)
>
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 72d5316180..e08ee21ee5 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -1774,6 +1774,7 @@ static void __init find_gnttab_region(struct domain *d,
> int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
> {
> unsigned int i;
> + int rc;
> struct vcpu *v = d->vcpu[0];
> struct cpu_user_regs *regs = &v->arch.cpu_info->guest_cpu_user_regs;
>
> @@ -1842,17 +1843,15 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
> }
> #endif
>
> - for ( i = 1; i < d->max_vcpus; i++ )
> + if ( (rc = vcpus_create(d)) )
> {
> - if ( vcpu_create(d, i) == NULL )
> - {
> - printk("Failed to allocate d%dv%d\n", d->domain_id, i);
> - return -ENOMEM;
> - }
> + printk("Failed to allocate d%dv%d\n", d->domain_id, d->max_vcpus);
> + return rc;
> + }
>
> - if ( is_64bit_domain(d) )
> + if ( is_64bit_domain(d) )
> + for ( i = 1; i < d->max_vcpus; i++ )
> vcpu_switch_to_aarch64_mode(d->vcpu[i]);
> - }
>
> domain_update_node_affinity(d);
>
> diff --git a/xen/arch/x86/mm/mem_sharing.c b/xen/arch/x86/mm/mem_sharing.c
> index 5c7a0ff30e..cd7f747c80 100644
> --- a/xen/arch/x86/mm/mem_sharing.c
> +++ b/xen/arch/x86/mm/mem_sharing.c
> @@ -1612,21 +1612,14 @@ int mem_sharing_fork_page(struct domain *d, gfn_t gfn, bool unsharing)
>
> static int bring_up_vcpus(struct domain *cd, struct domain *d)
> {
> - unsigned int i;
> int ret = -EINVAL;
>
> if ( d->max_vcpus != cd->max_vcpus ||
> (ret = cpupool_move_domain(cd, d->cpupool)) )
> return ret;
>
> - for ( i = 0; i < cd->max_vcpus; i++ )
> - {
> - if ( !d->vcpu[i] || cd->vcpu[i] )
> - continue;
> -
> - if ( !vcpu_create(cd, i) )
> - return -EINVAL;
> - }
> + if ( (ret = vcpus_create(cd)) )
> + return ret;
>
> domain_update_node_affinity(cd);
> return 0;
> diff --git a/xen/common/domain.c b/xen/common/domain.c
> index e16f1ac383..a0a3e51b15 100644
> --- a/xen/common/domain.c
> +++ b/xen/common/domain.c
> @@ -539,6 +539,30 @@ struct vcpu *vcpu_create(struct domain *d, unsigned int vcpu_id)
> return NULL;
> }
>
> +/*
> + * Create every not yet existing vcpu of d, up to d->max_vcpus. On failure,
> + * d->max_vcpus is rolled back to the id that failed, keeping d->vcpu[i]
> + * non-NULL for all i < d->max_vcpus.
> + */
> +int vcpus_create(struct domain *d)
> +{
> + unsigned int i;
> +
> + for ( i = 0; i < d->max_vcpus; i++ )
> + {
> + if ( d->vcpu[i] )
> + continue;
> +
> + if ( vcpu_create(d, i) == NULL )
> + {
> + d->max_vcpus = i;
> + return -EINVAL;
I think this should be -ENOMEM.
Juergen
OpenPGP_0xB0DE9DD628BF132F.asc
(application/pgp-keys, 3.6 KB)
-----BEGIN PGP PUBLIC KEY BLOCK----- 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 kt+z4drzFUyEjLM1vVvIMjkUoJs= =eeAB -----END PGP PUBLIC KEY BLOCK-----
OpenPGP_signature.asc
(application/pgp-signature, 495 B)
-----BEGIN PGP SIGNATURE----- wsB5BAABCAAjFiEEhRJncuj2BJSl0Jf3sN6d1ii/Ey8FAmqVN6AFAwAAAAAACgkQsN6d1ii/Ey8X QQgAlTH553EV8jyIlSfK2bSDz+kbZdEi1UnhF4JKCk/KS8xF04+XUmNTtbrJ7ha3iGpRTeQTsf4N gslWUG++oWAhMBZidPzGJ4D+583s+SQebgSJP22oe3RUfNsquivOFrff9bKbSzKNY8IQtqOxJX/E V6vSsfOA5ayd3+BPK1l911yqkWdRZWSj8Su5FRJjVGf8hIFjAsVbm0drKihz8PTZFG9qNUqWx9kF 9B32LNgKYGJI0JDPRdjomGfGGcItwvnZ3QDbMCeBV5EFqFJGnuVPYOhwCZO5g+cPikUK5IfOd/rK Z8tTbwGHvyCeOdlJDHqROqjIwehah5DGV2zF6xVl3w== =aWX+ -----END PGP SIGNATURE-----