domctl: also pause domain for "extended" context updates
authorJan Beulich <jbeulich@suse.com>
Thu, 6 Feb 2014 11:20:20 +0000 (12:20 +0100)
committerJan Beulich <jbeulich@suse.com>
Thu, 6 Feb 2014 11:20:20 +0000 (12:20 +0100)
This is not just for consistency with "base" context updates, but
actually needed so that guest side accesses can't race with control
domain side updates.

This would have been a security issue if XSA-77 hadn't waived them on
the affected domctl operation.

While looking at the code I also spotted a redundant NULL check in the
"base" context update handling code, which is being removed.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Release-acked-by: George Dunlap <george.dunlap@eu.citrix.com>
xen/arch/x86/domctl.c
xen/common/domctl.c

index 41cfd7c3cbbab1ef8761f1cc6f30b4848e8d0536..432a180865860a5274ea6c798b34dac9037c50a8 100644 (file)
@@ -853,6 +853,8 @@ long arch_do_domctl(
         }
         else
         {
+            if ( d == current->domain ) /* no domain_pause() */
+                break;
             ret = -EINVAL;
             if ( evc->size < offsetof(typeof(*evc), vmce) )
                 break;
@@ -861,6 +863,7 @@ long arch_do_domctl(
                 if ( !is_canonical_address(evc->sysenter_callback_eip) ||
                      !is_canonical_address(evc->syscall32_callback_eip) )
                     break;
+                domain_pause(d);
                 fixup_guest_code_selector(d, evc->sysenter_callback_cs);
                 v->arch.pv_vcpu.sysenter_callback_cs      =
                     evc->sysenter_callback_cs;
@@ -881,6 +884,8 @@ long arch_do_domctl(
                       (evc->syscall32_callback_cs & ~3) ||
                       evc->syscall32_callback_eip )
                 break;
+            else
+                domain_pause(d);
 
             BUILD_BUG_ON(offsetof(struct xen_domctl_ext_vcpucontext,
                                   mcg_cap) !=
@@ -899,6 +904,8 @@ long arch_do_domctl(
             }
             else
                 ret = 0;
+
+            domain_unpause(d);
         }
     }
     break;
index 904d27bb795c2888a0a8f096c763c8f77be80984..f237be4a7712824f0143277082f23112ef074152 100644 (file)
@@ -334,10 +334,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
         unsigned int vcpu = op->u.vcpucontext.vcpu;
         struct vcpu *v;
 
-        ret = -ESRCH;
-        if ( d == NULL )
-            break;
-
         ret = -EINVAL;
         if ( (d == current->domain) || /* no domain_pause() */
              (vcpu >= d->max_vcpus) || ((v = d->vcpu[vcpu]) == NULL) )