From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Xen-devel <xen-devel@lists.xen.org>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>,
Jan Beulich <JBeulich@suse.com>
Subject: [PATCH v3 1/2] x86/xstate: Use a guests CPUID policy, rather than allowing all features
Date: Thu, 19 Jul 2018 12:44:42 +0100 [thread overview]
Message-ID: <1532000683-23429-2-git-send-email-andrew.cooper3@citrix.com> (raw)
In-Reply-To: <1532000683-23429-1-git-send-email-andrew.cooper3@citrix.com>
It turns out that Xen has never enforced that a domain remain within the
xstate features advertised in CPUID.
The check of new_bv against xfeature_mask ensures that a domain stays within
the set of features that Xen has enabled in hardware (and therefore isn't a
security problem), but this does means that attempts to level a guest for
migration safety might not be effective if the guest ignores CPUID.
Check the CPUID policy in validate_xstate() (for incoming migration) and in
handle_xsetbv() (for guest XSETBV instructions). This subsumes the PKRU check
for PV guests in handle_xsetbv() (and also demonstrates that I should have
spotted this problem while reviewing c/s fbf9971241f).
For migration, this is correct despite the current (mis)ordering of data
because d->arch.cpuid is the applicable max policy.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
CC: Jan Beulich <JBeulich@suse.com>
v2:
* Leave valid_xcr0() alone and duplicate the checks in validate_xstate() and
handle_xsetbv().
v3:
* Note the migration safety in the commit message.
Backporting notes: This is safe in the restore case, but only back as far as
the introduction of cpuid_policy infrastructure. Before then, a restore
boolean needs to be plumbed down as well, and used to select between the
hardware maximum value and calls to {hvm,pv}_cpuid() to find the
toolstack-chosen level.
---
xen/arch/x86/domctl.c | 2 +-
xen/arch/x86/hvm/hvm.c | 2 +-
xen/arch/x86/xstate.c | 17 +++++++++++------
xen/include/asm-x86/xstate.h | 5 +++--
4 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index b973629..0423a0c 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -1170,7 +1170,7 @@ long arch_do_domctl(
if ( _xcr0_accum )
{
if ( evc->size >= PV_XSAVE_HDR_SIZE + XSTATE_AREA_MIN_SIZE )
- ret = validate_xstate(_xcr0, _xcr0_accum,
+ ret = validate_xstate(d, _xcr0, _xcr0_accum,
&_xsave_area->xsave_hdr);
}
else if ( !_xcr0 )
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 4ed24a4..1816faa 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -1254,7 +1254,7 @@ static int hvm_load_cpu_xsave_states(struct domain *d, hvm_domain_context_t *h)
ctxt = (struct hvm_hw_cpu_xsave *)&h->data[h->cur];
h->cur += desc->length;
- err = validate_xstate(ctxt->xcr0, ctxt->xcr0_accum,
+ err = validate_xstate(d, ctxt->xcr0, ctxt->xcr0_accum,
(const void *)&ctxt->save_area.xsave_hdr);
if ( err )
{
diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c
index b4aea4b..1fbb087 100644
--- a/xen/arch/x86/xstate.c
+++ b/xen/arch/x86/xstate.c
@@ -670,12 +670,17 @@ static bool valid_xcr0(u64 xcr0)
return !(xcr0 & X86_XCR0_BNDREGS) == !(xcr0 & X86_XCR0_BNDCSR);
}
-int validate_xstate(u64 xcr0, u64 xcr0_accum, const struct xsave_hdr *hdr)
+int validate_xstate(const struct domain *d, uint64_t xcr0, uint64_t xcr0_accum,
+ const struct xsave_hdr *hdr)
{
+ const struct cpuid_policy *cp = d->arch.cpuid;
+ uint64_t xcr0_max =
+ ((uint64_t)cp->xstate.xcr0_high << 32) | cp->xstate.xcr0_low;
unsigned int i;
if ( (hdr->xstate_bv & ~xcr0_accum) ||
(xcr0 & ~xcr0_accum) ||
+ (xcr0_accum & ~xcr0_max) ||
!valid_xcr0(xcr0) ||
!valid_xcr0(xcr0_accum) )
return -EINVAL;
@@ -694,18 +699,18 @@ int validate_xstate(u64 xcr0, u64 xcr0_accum, const struct xsave_hdr *hdr)
int handle_xsetbv(u32 index, u64 new_bv)
{
struct vcpu *curr = current;
+ const struct cpuid_policy *cp = curr->domain->arch.cpuid;
+ uint64_t xcr0_max =
+ ((uint64_t)cp->xstate.xcr0_high << 32) | cp->xstate.xcr0_low;
u64 mask;
if ( index != XCR_XFEATURE_ENABLED_MASK )
return -EOPNOTSUPP;
- if ( (new_bv & ~xfeature_mask) || !valid_xcr0(new_bv) )
+ if ( (new_bv & ~xcr0_max) ||
+ (new_bv & ~xfeature_mask) || !valid_xcr0(new_bv) )
return -EINVAL;
- /* XCR0.PKRU is disabled on PV mode. */
- if ( is_pv_vcpu(curr) && (new_bv & X86_XCR0_PKRU) )
- return -EOPNOTSUPP;
-
if ( !set_xcr0(new_bv) )
return -EFAULT;
diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h
index 86a4a1f..47f602b 100644
--- a/xen/include/asm-x86/xstate.h
+++ b/xen/include/asm-x86/xstate.h
@@ -97,8 +97,9 @@ void xsave(struct vcpu *v, uint64_t mask);
void xrstor(struct vcpu *v, uint64_t mask);
void xstate_set_init(uint64_t mask);
bool xsave_enabled(const struct vcpu *v);
-int __must_check validate_xstate(u64 xcr0, u64 xcr0_accum,
- const struct xsave_hdr *);
+int __must_check validate_xstate(const struct domain *d,
+ uint64_t xcr0, uint64_t xcr0_accum,
+ const struct xsave_hdr *hdr);
int __must_check handle_xsetbv(u32 index, u64 new_bv);
void expand_xsave_states(struct vcpu *v, void *dest, unsigned int size);
void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size);
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel
next prev parent reply other threads:[~2018-07-19 11:44 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-07-19 11:44 [PATCH v3 0/2] x86/xstate: Fixes and improvements to xsetbv handling Andrew Cooper
2018-07-19 11:44 ` Andrew Cooper [this message]
2018-07-27 9:28 ` [PATCH v3 1/2] x86/xstate: Use a guests CPUID policy, rather than allowing all features Jan Beulich
2018-07-27 9:37 ` Andrew Cooper
2018-07-27 10:18 ` Jan Beulich
2018-07-27 14:06 ` Jan Beulich
2018-07-19 11:44 ` [PATCH v3 2/2] x86/xstate: Make errors in xstate calculations more obvious by crashing the domain Andrew Cooper
2018-07-27 13:24 ` Jan Beulich
2018-07-27 13:35 ` Andrew Cooper
2018-07-31 10:37 ` [PATCH] x86/xstate: correct logging in handle_xsetbv() Jan Beulich
2018-07-31 10:38 ` Andrew Cooper
2018-07-19 18:48 ` [PATCH v3 0/2] x86/xstate: Fixes and improvements to xsetbv handling Jan Beulich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1532000683-23429-2-git-send-email-andrew.cooper3@citrix.com \
--to=andrew.cooper3@citrix.com \
--cc=JBeulich@suse.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).