]> xenbits.xensource.com Git - people/sstabellini/xen-unstable.git/.git/commitdiff
xen/cpu: Distinguish "cpu already in that state" in cpu_{up,down}()
authorAndrew Cooper <andrew.cooper3@citrix.com>
Tue, 2 Apr 2019 13:21:56 +0000 (14:21 +0100)
committerAndrew Cooper <andrew.cooper3@citrix.com>
Thu, 4 Apr 2019 13:32:41 +0000 (14:32 +0100)
All methods of querying the online state of a CPU are racy without the hotplug
lock held, which can lead to a TOCTOU race trying to online or offline CPUs.

Distinguish this case with -EEXIST rather than -EINVAL, so the caller can take
other actions if necessary.

While adjusting this, rework the code slightly to fold the exit paths, which
results in a minor reduction in compiled code size.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/common/cpu.c

index a6efc5e604a91f45ad76fd0bf463a8812f3bd046..f388d8977d8c34fefacb9e153f1ae1f2411e6fff 100644 (file)
@@ -103,11 +103,13 @@ int cpu_down(unsigned int cpu)
     if ( !cpu_hotplug_begin() )
         return -EBUSY;
 
-    if ( (cpu >= nr_cpu_ids) || (cpu == 0) || !cpu_online(cpu) )
-    {
-        cpu_hotplug_done();
-        return -EINVAL;
-    }
+    err = -EINVAL;
+    if ( (cpu >= nr_cpu_ids) || (cpu == 0) )
+        goto out;
+
+    err = -EEXIST;
+    if ( !cpu_online(cpu) )
+        goto out;
 
     err = cpu_notifier_call_chain(cpu, CPU_DOWN_PREPARE, &nb, false);
     if ( err )
@@ -130,6 +132,7 @@ int cpu_down(unsigned int cpu)
 
  fail:
     cpu_notifier_call_chain(cpu, CPU_DOWN_FAILED, &nb, true);
+ out:
     cpu_hotplug_done();
     return err;
 }
@@ -142,11 +145,13 @@ int cpu_up(unsigned int cpu)
     if ( !cpu_hotplug_begin() )
         return -EBUSY;
 
-    if ( (cpu >= nr_cpu_ids) || cpu_online(cpu) || !cpu_present(cpu) )
-    {
-        cpu_hotplug_done();
-        return -EINVAL;
-    }
+    err = -EINVAL;
+    if ( (cpu >= nr_cpu_ids) || !cpu_present(cpu) )
+        goto out;
+
+    err = -EEXIST;
+    if ( cpu_online(cpu) )
+        goto out;
 
     err = cpu_notifier_call_chain(cpu, CPU_UP_PREPARE, &nb, false);
     if ( err )
@@ -165,6 +170,7 @@ int cpu_up(unsigned int cpu)
 
  fail:
     cpu_notifier_call_chain(cpu, CPU_UP_CANCELED, &nb, true);
+ out:
     cpu_hotplug_done();
     return err;
 }