mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
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@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> x86/domctl: further fix to XEN_DOMCTL_[gs]etvcpuextstate Do not clobber errors from certain codepaths. Clobbering of -EINVAL from failing "evc->size <= PV_XSAVE_SIZE(_xcr0_accum)" was a pre-existing bug. However, clobbering -EINVAL/-EFAULT from the get codepath was a bug unintentionally introduced by090ca8c1"x86/domctl: two functional fixes to XEN_DOMCTL_[gs]etvcpuextstate". Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> master commit:090ca8c155master date: 2014-06-05 17:52:57 +0200 master commit:895661ae98master date: 2014-06-10 12:03:16 +0200
This commit is contained in:
1 parent
29cdbd115d
commit
5cd10bbcf2
1 file changed
+29
-26
+29
-26
@@ -1075,45 +1075,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
|
||||
{
|
||||
@@ -1162,12 +1165,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;
|
||||
@@ -1175,8 +1180,6 @@ long arch_do_domctl(
|
||||
xfree(receive_buf);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
vcpuextstate_out:
|
||||
if ( domctl->cmd == XEN_DOMCTL_getvcpuextstate )
|
||||
copyback = 1;
|
||||
|
||||