]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
x86/domain: Fix domlist_insert() updating the domain hash
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 31 Jul 2024 19:05:21 +0000 (20:05 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 31 Jul 2024 22:19:42 +0000 (23:19 +0100)
A last minute review request was to dedup the expression calculating the
domain hash bucket.

While the code reads correctly, it is buggy because rcu_assign_pointer() is a
deeply misleading API assigning by name not value, and - contrary to it's name
- does not hide an indirection.

Therefore, rcu_assign_pointer(bucket, d); updates the local bucket variable on
the stack, not domain_hash[], causing all subsequent domid lookups to fail.

Rework the logic to use pd in the same way that domlist_remove() does.

Fixes: 19995bc70cc6 ("xen/domain: Factor domlist_{insert,remove}() out of domain_{create,destroy}()")
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/common/domain.c

index 8d8f40ccb2455b90a33e60cbe615c7001d148e23..92263a4fbdc57159b4a32d9d4ee038f9f37804ed 100644 (file)
@@ -70,7 +70,7 @@ struct domain *domain_list;
  */
 static void domlist_insert(struct domain *d)
 {
-    struct domain **pd, *bucket;
+    struct domain **pd;
 
     spin_lock(&domlist_update_lock);
 
@@ -79,12 +79,12 @@ static void domlist_insert(struct domain *d)
         if ( (*pd)->domain_id > d->domain_id )
             break;
 
-    bucket = domain_hash[DOMAIN_HASH(d->domain_id)];
-
     d->next_in_list = *pd;
-    d->next_in_hashbucket = bucket;
     rcu_assign_pointer(*pd, d);
-    rcu_assign_pointer(bucket, d);
+
+    pd = &domain_hash[DOMAIN_HASH(d->domain_id)];
+    d->next_in_hashbucket = *pd;
+    rcu_assign_pointer(*pd, d);
 
     spin_unlock(&domlist_update_lock);
 }