|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 4/4] x86/domctl: Two functional fixes to XEN_DOMCTL_[gs]etvcpuextstate
Interacting with the vcpu itself should be protected by vcpu_pause().
Buggy/naive toolstacks might encounter adverse interaction with a vcpu context
switch, or increase of xcr0_accum. There are no much problems with current
in-tree code.
Explicitly permit a NULL guest handle as being a request for size. It is the
prevailing Xen style, and without it, valgrind's ioctl handler is unable to
determine whether evc->buffer actually got written to.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CC: Keir Fraser <keir@xxxxxxx>
CC: Jan Beulich <JBeulich@xxxxxxxx>
---
There are further issues which are specifically not fixed in this patch.
There is a race condition between querying evc->size and trying to write the
xsave state into a buffer that size, if the vcpu goes and increases xcr0_accum
in the meantime.
The legacy migration stream is sufficiently inflexible that I can't find a way
of doing it in a backwards compatible way which still works in a heterogeneous
migration case.
As there are further problems anyway with the legacy migration stream anyway
(vcpus with different xcr0_accum's will result in stream corruption in
xc_domain_restore()), I intend to wait until the v2 code is present and v1
code removed, at which point this issue shall be trivial to fix.
---
xen/arch/x86/domctl.c | 53 +++++++++++++++++++++++++++----------------------
1 file changed, 29 insertions(+), 24 deletions(-)
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index 8f5b287..99163f9 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1097,45 +1097,48 @@ long arch_do_domctl(
((v = d->vcpu[evc->vcpu]) == NULL) )
goto vcpuextstate_out;
+ ret = -EINVAL;
+ if ( v == current ) /* no vcpu_pause() */
+ goto vcpuextstate_out;
+
if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
{
- unsigned int size = PV_XSAVE_SIZE(v->arch.xcr0_accum);
+ unsigned int size;
- if ( !evc->size && !evc->xfeature_mask )
+ ret = 0;
+ vcpu_pause(v);
+
+ size = PV_XSAVE_SIZE(v->arch.xcr0_accum);
+ if ( (!evc->size && !evc->xfeature_mask) ||
+ guest_handle_is_null(evc->buffer) )
{
evc->xfeature_mask = xfeature_mask;
evc->size = size;
- ret = 0;
+ vcpu_unpause(v);
goto vcpuextstate_out;
}
+
if ( evc->size != size || evc->xfeature_mask != xfeature_mask )
- {
ret = -EINVAL;
- goto vcpuextstate_out;
- }
- if ( copy_to_guest_offset(domctl->u.vcpuextstate.buffer,
- offset, (void *)&v->arch.xcr0,
- sizeof(v->arch.xcr0)) )
- {
+
+ if ( !ret && copy_to_guest_offset(evc->buffer, offset,
+ (void *)&v->arch.xcr0,
+ sizeof(v->arch.xcr0)) )
ret = -EFAULT;
- goto vcpuextstate_out;
- }
+
offset += sizeof(v->arch.xcr0);
- if ( copy_to_guest_offset(domctl->u.vcpuextstate.buffer,
- offset, (void *)&v->arch.xcr0_accum,
- sizeof(v->arch.xcr0_accum)) )
- {
+ if ( !ret && copy_to_guest_offset(evc->buffer, offset,
+ (void *)&v->arch.xcr0_accum,
+ sizeof(v->arch.xcr0_accum)) )
ret = -EFAULT;
- goto vcpuextstate_out;
- }
+
offset += sizeof(v->arch.xcr0_accum);
- if ( copy_to_guest_offset(domctl->u.vcpuextstate.buffer,
- offset, (void *)v->arch.xsave_area,
- size - 2 * sizeof(uint64_t)) )
- {
+ if ( !ret && copy_to_guest_offset(evc->buffer, offset,
+ (void *)v->arch.xsave_area,
+ size - 2 * sizeof(uint64_t)) )
ret = -EFAULT;
- goto vcpuextstate_out;
- }
+
+ vcpu_unpause(v);
}
else
{
@@ -1183,12 +1186,14 @@ long arch_do_domctl(
if ( evc->size <= PV_XSAVE_SIZE(_xcr0_accum) )
{
+ vcpu_pause(v);
v->arch.xcr0 = _xcr0;
v->arch.xcr0_accum = _xcr0_accum;
if ( _xcr0_accum & XSTATE_NONLAZY )
v->arch.nonlazy_xstate_used = 1;
memcpy(v->arch.xsave_area, _xsave_area,
evc->size - 2 * sizeof(uint64_t));
+ vcpu_unpause(v);
}
else
ret = -EINVAL;
--
1.7.10.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |