system/xen: Updated for version 4.7.1.

Signed-off-by: Mario Preksavec <mario@slackware.hr>
This commit is contained in:
Mario Preksavec 2016-11-09 20:48:25 +01:00 committed by David Spencer
parent 4d4008a1a1
commit 78e62f339c
17 changed files with 12 additions and 797 deletions

View file

@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 4.4.19 Kernel Configuration
# Linux/x86 4.4.29 Kernel Configuration
#
# CONFIG_64BIT is not set
CONFIG_X86_32=y
@ -379,7 +379,7 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
# CONFIG_PARAVIRT_DEBUG is not set
# CONFIG_PARAVIRT_SPINLOCKS is not set
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_XEN=y
CONFIG_XEN_DOM0=y
CONFIG_XEN_PVHVM=y

View file

@ -1,6 +1,6 @@
#
# Automatically generated file; DO NOT EDIT.
# Linux/x86 4.4.19 Kernel Configuration
# Linux/x86 4.4.29 Kernel Configuration
#
CONFIG_64BIT=y
CONFIG_X86_64=y
@ -390,7 +390,7 @@ CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_HYPERVISOR_GUEST=y
CONFIG_PARAVIRT=y
# CONFIG_PARAVIRT_DEBUG is not set
# CONFIG_PARAVIRT_SPINLOCKS is not set
CONFIG_PARAVIRT_SPINLOCKS=y
CONFIG_XEN=y
CONFIG_XEN_DOM0=y
CONFIG_XEN_PVHVM=y

View file

@ -5,8 +5,8 @@
# Written by Chris Abela <chris.abela@maltats.com>, 20100515
# Modified by Mario Preksavec <mario@slackware.hr>
KERNEL=${KERNEL:-4.4.19}
XEN=${XEN:-4.7.0}
KERNEL=${KERNEL:-4.4.29}
XEN=${XEN:-4.7.1}
BOOTLOADER=${BOOTLOADER:-lilo}
ROOTMOD=${ROOTMOD:-ext4}

View file

@ -7,7 +7,7 @@
set -e
KERNEL=${KERNEL:-4.4.19}
KERNEL=${KERNEL:-4.4.29}
# Build an image for the root file system and another for the swap
# Default values : 8GB and 500MB resepectively.

View file

@ -1,12 +0,0 @@
diff --git a/tools/libxc/xc_sr_save_x86_pv.c b/tools/libxc/xc_sr_save_x86_pv.c
index 4a29460..7043409 100644
--- a/tools/libxc/xc_sr_save_x86_pv.c
+++ b/tools/libxc/xc_sr_save_x86_pv.c
@@ -430,6 +430,8 @@ static int map_p2m_list(struct xc_sr_context *ctx, uint64_t p2m_cr3)
if ( level == 2 )
{
+ if ( saved_idx == idx_end )
+ saved_idx++;
max_pfn = ((xen_pfn_t)saved_idx << 9) * fpp - 1;
if ( max_pfn < ctx->x86_pv.max_pfn )

View file

@ -23,8 +23,8 @@
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
PRGNAM=xen
VERSION=${VERSION:-4.7.0}
BUILD=${BUILD:-2}
VERSION=${VERSION:-4.7.1}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
SEABIOS=${SEABIOS:-1.9.2}
@ -117,9 +117,6 @@ for i in $CWD/xsa/* ; do
esac
done
# Upstream fixes
patch -p1 <$CWD/patches/xen-4.7-regression-when-saving-a-pv-guest.patch
# Don't link with libssh and bluez by default
sed "s/@@CONF_LIBSSH2@@/$CONF_LIBSSH2/;s/@@CONF_BLUEZ@@/$CONF_BLUEZ/" \
$CWD/patches/qemu_configure_options.diff | patch -p1

View file

@ -1,7 +1,7 @@
PRGNAM="xen"
VERSION="4.7.0"
VERSION="4.7.1"
HOMEPAGE="http://www.xenproject.org/"
DOWNLOAD="http://mirror.slackware.hr/sources/xen/xen-4.7.0.tar.gz \
DOWNLOAD="http://mirror.slackware.hr/sources/xen/xen-4.7.1.tar.gz \
http://mirror.slackware.hr/sources/xen-extfiles/ipxe-git-9a93db3f0947484e30e753bbd61a10b17336e20e.tar.gz \
http://mirror.slackware.hr/sources/xen-extfiles/lwip-1.3.0.tar.gz \
http://mirror.slackware.hr/sources/xen-extfiles/zlib-1.2.3.tar.gz \
@ -13,7 +13,7 @@ DOWNLOAD="http://mirror.slackware.hr/sources/xen/xen-4.7.0.tar.gz \
http://mirror.slackware.hr/sources/xen-extfiles/tpm_emulator-0.7.4.tar.gz \
http://mirror.slackware.hr/sources/xen-extfiles/seabios-1.9.2.tar.gz
http://mirror.slackware.hr/sources/xen-extfiles/ovmf-git-52a99493cce88a9d4ec8a02d7f1bd1a1001ce60d.tar.gz"
MD5SUM="3aa4e01bf37a3a5bc8572907cb88e649 \
MD5SUM="8e258d87a1008a3200eec6989e164fa4 \
7496268cebf47d5c9ccb0696e3b26065 \
36cc57650cffda9a0269493be2a169bb \
debc62758716a169df9f62e6ab2bc634 \

View file

@ -1,102 +0,0 @@
From 00593655e231ed5ea20704120037026e33b83fbb Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Mon, 11 Jul 2016 14:32:03 +0100
Subject: [PATCH] x86/pv: Remove unsafe bits from the mod_l?_entry() fastpath
All changes in writeability and cacheability must go through full
re-validation.
Rework the logic as a whitelist, to make it clearer to follow.
This is XSA-182
Reported-by: Jérémie Boutoille <jboutoille@ext.quarkslab.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Tim Deegan <tim@xen.org>
---
xen/arch/x86/mm.c | 28 ++++++++++++++++------------
xen/include/asm-x86/page.h | 1 +
2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index dbcf6cb..56ca19f 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1852,6 +1852,14 @@ static inline int update_intpte(intpte_t *p,
_t ## e_get_intpte(_o), _t ## e_get_intpte(_n), \
(_m), (_v), (_ad))
+/*
+ * PTE flags that a guest may change without re-validating the PTE.
+ * All other bits affect translation, caching, or Xen's safety.
+ */
+#define FASTPATH_FLAG_WHITELIST \
+ (_PAGE_NX_BIT | _PAGE_AVAIL_HIGH | _PAGE_AVAIL | _PAGE_GLOBAL | \
+ _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_USER)
+
/* Update the L1 entry at pl1e to new value nl1e. */
static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
unsigned long gl1mfn, int preserve_ad,
@@ -1891,9 +1899,8 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e,
nl1e = l1e_from_pfn(page_to_mfn(page), l1e_get_flags(nl1e));
}
- /* Fast path for identical mapping, r/w, presence, and cachability. */
- if ( !l1e_has_changed(ol1e, nl1e,
- PAGE_CACHE_ATTRS | _PAGE_RW | _PAGE_PRESENT) )
+ /* Fast path for sufficiently-similar mappings. */
+ if ( !l1e_has_changed(ol1e, nl1e, ~FASTPATH_FLAG_WHITELIST) )
{
adjust_guest_l1e(nl1e, pt_dom);
rc = UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
@@ -1970,11 +1977,8 @@ static int mod_l2_entry(l2_pgentry_t *pl2e,
return -EINVAL;
}
- /* Fast path for identical mapping and presence. */
- if ( !l2e_has_changed(ol2e, nl2e,
- unlikely(opt_allow_superpage)
- ? _PAGE_PSE | _PAGE_RW | _PAGE_PRESENT
- : _PAGE_PRESENT) )
+ /* Fast path for sufficiently-similar mappings. */
+ if ( !l2e_has_changed(ol2e, nl2e, ~FASTPATH_FLAG_WHITELIST) )
{
adjust_guest_l2e(nl2e, d);
if ( UPDATE_ENTRY(l2, pl2e, ol2e, nl2e, pfn, vcpu, preserve_ad) )
@@ -2039,8 +2043,8 @@ static int mod_l3_entry(l3_pgentry_t *pl3e,
return -EINVAL;
}
- /* Fast path for identical mapping and presence. */
- if ( !l3e_has_changed(ol3e, nl3e, _PAGE_PRESENT) )
+ /* Fast path for sufficiently-similar mappings. */
+ if ( !l3e_has_changed(ol3e, nl3e, ~FASTPATH_FLAG_WHITELIST) )
{
adjust_guest_l3e(nl3e, d);
rc = UPDATE_ENTRY(l3, pl3e, ol3e, nl3e, pfn, vcpu, preserve_ad);
@@ -2103,8 +2107,8 @@ static int mod_l4_entry(l4_pgentry_t *pl4e,
return -EINVAL;
}
- /* Fast path for identical mapping and presence. */
- if ( !l4e_has_changed(ol4e, nl4e, _PAGE_PRESENT) )
+ /* Fast path for sufficiently-similar mappings. */
+ if ( !l4e_has_changed(ol4e, nl4e, ~FASTPATH_FLAG_WHITELIST) )
{
adjust_guest_l4e(nl4e, d);
rc = UPDATE_ENTRY(l4, pl4e, ol4e, nl4e, pfn, vcpu, preserve_ad);
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index 224852a..4ae387f 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -313,6 +313,7 @@ void efi_update_l4_pgtable(unsigned int l4idx, l4_pgentry_t);
#define _PAGE_AVAIL2 _AC(0x800,U)
#define _PAGE_AVAIL _AC(0xE00,U)
#define _PAGE_PSE_PAT _AC(0x1000,U)
+#define _PAGE_AVAIL_HIGH (_AC(0x7ff, U) << 12)
#define _PAGE_NX (cpu_has_nx ? _PAGE_NX_BIT : 0)
/* non-architectural flags */
#define _PAGE_PAGED 0x2000U
--
2.1.4

View file

@ -1,75 +0,0 @@
From 2fd4f34058fb5f87fbd80978dbd2cb458aff565d Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Wed, 15 Jun 2016 18:32:14 +0100
Subject: [PATCH] x86/entry: Avoid SMAP violation in
compat_create_bounce_frame()
A 32bit guest kernel might be running on user mappings.
compat_create_bounce_frame() must whitelist its guest accesses to avoid
risking a SMAP violation.
For both variants of create_bounce_frame(), re-blacklist user accesses if
execution exits via an exception table redirection.
This is XSA-183 / CVE-2016-6259
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
v2:
* Include CLAC on the exit paths from compat_create_bounce_frame which occur
from faults attempting to load %fs
* Reposition ASM_STAC to avoid breaking the macro-op fusion of test/jz
---
xen/arch/x86/x86_64/compat/entry.S | 3 +++
xen/arch/x86/x86_64/entry.S | 2 ++
2 files changed, 5 insertions(+)
diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S
index 7f02afd..e80c53c 100644
--- a/xen/arch/x86/x86_64/compat/entry.S
+++ b/xen/arch/x86/x86_64/compat/entry.S
@@ -318,6 +318,7 @@ ENTRY(compat_int80_direct_trap)
compat_create_bounce_frame:
ASSERT_INTERRUPTS_ENABLED
mov %fs,%edi
+ ASM_STAC
testb $2,UREGS_cs+8(%rsp)
jz 1f
/* Push new frame at registered guest-OS stack base. */
@@ -364,6 +365,7 @@ compat_create_bounce_frame:
movl TRAPBOUNCE_error_code(%rdx),%eax
.Lft8: movl %eax,%fs:(%rsi) # ERROR CODE
1:
+ ASM_CLAC
/* Rewrite our stack frame and return to guest-OS mode. */
/* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */
andl $~(X86_EFLAGS_VM|X86_EFLAGS_RF|\
@@ -403,6 +405,7 @@ compat_crash_page_fault_4:
addl $4,%esi
compat_crash_page_fault:
.Lft14: mov %edi,%fs
+ ASM_CLAC
movl %esi,%edi
call show_page_walk
jmp dom_crash_sync_extable
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index ad8c64c..f7178cd 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -420,9 +420,11 @@ domain_crash_page_fault_16:
domain_crash_page_fault_8:
addq $8,%rsi
domain_crash_page_fault:
+ ASM_CLAC
movq %rsi,%rdi
call show_page_walk
ENTRY(dom_crash_sync_extable)
+ ASM_CLAC
# Get out of the guest-save area of the stack.
GET_STACK_END(ax)
leaq STACK_CPUINFO_FIELD(guest_cpu_user_regs)(%rax),%rsp
--
2.1.4

View file

@ -1,43 +0,0 @@
From 17d8c4e47dfb41cb6778520ff2eab7a11fe12dfd Mon Sep 17 00:00:00 2001
From: P J P <ppandit@redhat.com>
Date: Tue, 26 Jul 2016 15:31:59 +0100
Subject: [PATCH] virtio: error out if guest exceeds virtqueue size
A broken or malicious guest can submit more requests than the virtqueue
size permits.
The guest can submit requests without bothering to wait for completion
and is therefore not bound by virtqueue size. This requires reusing
vring descriptors in more than one request, which is incorrect but
possible. Processing a request allocates a VirtQueueElement and
therefore causes unbounded memory allocation controlled by the guest.
Exit with an error if the guest provides more requests than the
virtqueue size permits. This bounds memory allocation and makes the
buggy guest visible to the user.
Reported-by: Zhenhao Hong <zhenhaohong@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
hw/virtio.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/virtio.c b/hw/virtio.c
index c26feff..42897bf 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -421,6 +421,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
/* When we start there are none of either input nor output. */
elem->out_num = elem->in_num = 0;
+ if (vq->inuse >= vq->vring.num) {
+ fprintf(stderr, "Virtqueue size exceeded");
+ exit(1);
+ }
+
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
do {
struct iovec *sg;
--
2.1.4

View file

@ -1,43 +0,0 @@
From e469db25d6b2e5c71cd15451889226641c53a5cd Mon Sep 17 00:00:00 2001
From: P J P <ppandit@redhat.com>
Date: Mon, 25 Jul 2016 17:37:18 +0530
Subject: [PATCH] virtio: error out if guest exceeds virtqueue size
A broken or malicious guest can submit more requests than the virtqueue
size permits.
The guest can submit requests without bothering to wait for completion
and is therefore not bound by virtqueue size. This requires reusing
vring descriptors in more than one request, which is incorrect but
possible. Processing a request allocates a VirtQueueElement and
therefore causes unbounded memory allocation controlled by the guest.
Exit with an error if the guest provides more requests than the
virtqueue size permits. This bounds memory allocation and makes the
buggy guest visible to the user.
Reported-by: Zhenhao Hong <zhenhaohong@gmail.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
hw/virtio/virtio.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index d24f775..f8ac0fb 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -483,6 +483,11 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
max = vq->vring.num;
+ if (vq->inuse >= max) {
+ error_report("Virtqueue size exceeded");
+ exit(1);
+ }
+
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
if (virtio_vdev_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX)) {
vring_set_avail_event(vq, vq->last_avail_idx);
--
2.1.4

View file

@ -1,38 +0,0 @@
From 30aba4992b18245c436f16df7326a16c01a51570 Mon Sep 17 00:00:00 2001
From: Jan Beulich <jbeulich@suse.com>
Date: Mon, 8 Aug 2016 10:58:12 +0100
Subject: x86/32on64: don't allow recursive page tables from L3
L3 entries are special in PAE mode, and hence can't reasonably be used
for setting up recursive (and hence linear) page table mappings. Since
abuse is possible when the guest in fact gets run on 4-level page
tables, this needs to be excluded explicitly.
This is XSA-185.
Reported-by: Jérémie Boutoille <jboutoille@ext.quarkslab.com>
Reported-by: 栾尚聪(好风) <shangcong.lsc@alibaba-inc.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
xen/arch/x86/mm.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
index 109b8be..69b8b8d 100644
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -1122,7 +1122,9 @@ get_page_from_l3e(
rc = get_page_and_type_from_pagenr(
l3e_get_pfn(l3e), PGT_l2_page_table, d, partial, 1);
- if ( unlikely(rc == -EINVAL) && get_l3_linear_pagetable(l3e, pfn, d) )
+ if ( unlikely(rc == -EINVAL) &&
+ !is_pv_32bit_domain(d) &&
+ get_l3_linear_pagetable(l3e, pfn, d) )
rc = 0;
return rc;
--
2.1.4

View file

@ -1,73 +0,0 @@
From e938be013ba73ff08fa4f1d8670501aacefde7fb Mon Sep 17 00:00:00 2001
From: Andrew Cooper <andrew.cooper3@citrix.com>
Date: Fri, 22 Jul 2016 16:02:54 +0000
Subject: [PATCH 1/2] x86/emulate: Correct boundary interactions of emulated
instructions
This reverts most of c/s 0640ffb6 "x86emul: fix rIP handling".
Experimentally, in long mode processors will execute an instruction stream
which crosses the 64bit -1 -> 0 virtual boundary, whether the instruction
boundary is aligned on the virtual boundary, or is misaligned.
In compatibility mode, Intel processors will execute an instruction stream
which crosses the 32bit -1 -> 0 virtual boundary, while AMD processors raise a
segmentation fault. Xen's segmentation behaviour matches AMD.
For 16bit code, hardware does not ever truncated %ip. %eip is always used and
behaves normally as a 32bit register, including in 16bit protected mode
segments, as well as in Real and Unreal mode.
This is XSA-186
Reported-by: Brian Marcotte <marcotte@panix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
---
xen/arch/x86/x86_emulate/x86_emulate.c | 22 ++++------------------
1 file changed, 4 insertions(+), 18 deletions(-)
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c
index d5a56cf..bf3529a 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1570,10 +1570,6 @@ x86_emulate(
#endif
}
- /* Truncate rIP to def_ad_bytes (2 or 4) if necessary. */
- if ( def_ad_bytes < sizeof(_regs.eip) )
- _regs.eip &= (1UL << (def_ad_bytes * 8)) - 1;
-
/* Prefix bytes. */
for ( ; ; )
{
@@ -3906,21 +3902,11 @@ x86_emulate(
/* Commit shadow register state. */
_regs.eflags &= ~EFLG_RF;
- switch ( __builtin_expect(def_ad_bytes, sizeof(_regs.eip)) )
- {
- uint16_t ip;
- case 2:
- ip = _regs.eip;
- _regs.eip = ctxt->regs->eip;
- *(uint16_t *)&_regs.eip = ip;
- break;
-#ifdef __x86_64__
- case 4:
- _regs.rip = _regs._eip;
- break;
-#endif
- }
+ /* Zero the upper 32 bits of %rip if not in long mode. */
+ if ( def_ad_bytes < sizeof(_regs.eip) )
+ _regs.eip = (uint32_t)_regs.eip;
+
*ctxt->regs = _regs;
done:
--
2.1.4

View file

@ -1,28 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: hvm/fep: Allow testing of instructions crossing the -1 -> 0 virtual boundary
The Force Emulation Prefix is named to follow its PV counterpart for cpuid or
rdtsc, but isn't really an instruction prefix. It behaves as a break-out into
Xen, with the purpose of emulating the next instruction in the current state.
It is important to be able to test legal situations which occur in real
hardware, including instruction which cross certain boundaries, and
instructions starting at 0.
Reported-by: Brian Marcotte <marcotte@panix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3905,6 +3905,10 @@ void hvm_ud_intercept(struct cpu_user_re
{
regs->eip += sizeof(sig);
regs->eflags &= ~X86_EFLAGS_RF;
+
+ /* Zero the upper 32 bits of %rip if not in long mode. */
+ if ( !(hvm_long_mode_enabled(cur) && cs.attr.fields.l) )
+ regs->eip = regs->_eip;
}
}

View file

@ -1,42 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/shadow: Avoid overflowing sh_ctxt->seg_reg[]
hvm_get_seg_reg() does not perform a range check on its input segment, calls
hvm_get_segment_register() and writes straight into sh_ctxt->seg_reg[].
x86_seg_none is outside the bounds of sh_ctxt->seg_reg[], and will hit a BUG()
in {vmx,svm}_get_segment_register().
HVM guests running with shadow paging can end up performing a virtual to
linear translation with x86_seg_none. This is used for addresses which are
already linear. However, none of this is a legitimate pagetable update, so
fail the emulation in such a case.
This is XSA-187
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Tim Deegan <tim@xen.org>
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -140,9 +140,18 @@ static int hvm_translate_linear_addr(
struct sh_emulate_ctxt *sh_ctxt,
unsigned long *paddr)
{
- struct segment_register *reg = hvm_get_seg_reg(seg, sh_ctxt);
+ struct segment_register *reg;
int okay;
+ /*
+ * Can arrive here with non-user segments. However, no such cirucmstance
+ * is part of a legitimate pagetable update, so fail the emulation.
+ */
+ if ( !is_x86_user_segment(seg) )
+ return X86EMUL_UNHANDLEABLE;
+
+ reg = hvm_get_seg_reg(seg, sh_ctxt);
+
okay = hvm_virtual_to_linear_addr(
seg, reg, offset, bytes, access_type, sh_ctxt->ctxt.addr_size, paddr);

View file

@ -1,153 +0,0 @@
From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86/segment: Bounds check accesses to emulation ctxt->seg_reg[]
HVM HAP codepaths have space for all segment registers in the seg_reg[]
cache (with x86_seg_none still risking an array overrun), while the shadow
codepaths only have space for the user segments.
Range check the input segment of *_get_seg_reg() against the size of the array
used to cache the results, to avoid overruns in the case that the callers
don't filter their input suitably.
Subsume the is_x86_user_segment(seg) checks from the shadow code, which were
an incomplete attempt at range checking, and are now superceeded. Make
hvm_get_seg_reg() static, as it is not used outside of shadow/common.c
No functional change, but far easier to reason that no overflow is possible.
Reported-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Acked-by: Tim Deegan <tim@xen.org>
Acked-by: Jan Beulich <jbeulich@suse.com>
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -534,6 +534,8 @@ static int hvmemul_virtual_to_linear(
*reps = min_t(unsigned long, *reps, max_reps);
reg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
+ if ( IS_ERR(reg) )
+ return -PTR_ERR(reg);
if ( (hvmemul_ctxt->ctxt.regs->eflags & X86_EFLAGS_DF) && (*reps > 1) )
{
@@ -1369,6 +1371,10 @@ static int hvmemul_read_segment(
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
+
+ if ( IS_ERR(sreg) )
+ return -PTR_ERR(sreg);
+
memcpy(reg, sreg, sizeof(struct segment_register));
return X86EMUL_OKAY;
}
@@ -1382,6 +1388,9 @@ static int hvmemul_write_segment(
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
struct segment_register *sreg = hvmemul_get_seg_reg(seg, hvmemul_ctxt);
+ if ( IS_ERR(sreg) )
+ return -PTR_ERR(sreg);
+
memcpy(sreg, reg, sizeof(struct segment_register));
__set_bit(seg, &hvmemul_ctxt->seg_reg_dirty);
@@ -1934,10 +1943,17 @@ void hvm_emulate_writeback(
}
}
+/*
+ * Callers which pass a known in-range x86_segment can rely on the return
+ * pointer being valid. Other callers must explicitly check for errors.
+ */
struct segment_register *hvmemul_get_seg_reg(
enum x86_segment seg,
struct hvm_emulate_ctxt *hvmemul_ctxt)
{
+ if ( seg < 0 || seg >= ARRAY_SIZE(hvmemul_ctxt->seg_reg) )
+ return ERR_PTR(-X86EMUL_UNHANDLEABLE);
+
if ( !__test_and_set_bit(seg, &hvmemul_ctxt->seg_reg_accessed) )
hvm_get_segment_register(current, seg, &hvmemul_ctxt->seg_reg[seg]);
return &hvmemul_ctxt->seg_reg[seg];
--- a/xen/arch/x86/mm/shadow/common.c
+++ b/xen/arch/x86/mm/shadow/common.c
@@ -123,10 +123,19 @@ __initcall(shadow_audit_key_init);
/* x86 emulator support for the shadow code
*/
-struct segment_register *hvm_get_seg_reg(
+/*
+ * Callers which pass a known in-range x86_segment can rely on the return
+ * pointer being valid. Other callers must explicitly check for errors.
+ */
+static struct segment_register *hvm_get_seg_reg(
enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt)
{
- struct segment_register *seg_reg = &sh_ctxt->seg_reg[seg];
+ struct segment_register *seg_reg;
+
+ if ( seg < 0 || seg >= ARRAY_SIZE(sh_ctxt->seg_reg) )
+ return ERR_PTR(-X86EMUL_UNHANDLEABLE);
+
+ seg_reg = &sh_ctxt->seg_reg[seg];
if ( !__test_and_set_bit(seg, &sh_ctxt->valid_seg_regs) )
hvm_get_segment_register(current, seg, seg_reg);
return seg_reg;
@@ -143,14 +152,9 @@ static int hvm_translate_linear_addr(
struct segment_register *reg;
int okay;
- /*
- * Can arrive here with non-user segments. However, no such cirucmstance
- * is part of a legitimate pagetable update, so fail the emulation.
- */
- if ( !is_x86_user_segment(seg) )
- return X86EMUL_UNHANDLEABLE;
-
reg = hvm_get_seg_reg(seg, sh_ctxt);
+ if ( IS_ERR(reg) )
+ return -PTR_ERR(reg);
okay = hvm_virtual_to_linear_addr(
seg, reg, offset, bytes, access_type, sh_ctxt->ctxt.addr_size, paddr);
@@ -253,9 +257,6 @@ hvm_emulate_write(enum x86_segment seg,
unsigned long addr;
int rc;
- if ( !is_x86_user_segment(seg) )
- return X86EMUL_UNHANDLEABLE;
-
/* How many emulations could we save if we unshadowed on stack writes? */
if ( seg == x86_seg_ss )
perfc_incr(shadow_fault_emulate_stack);
@@ -283,7 +284,7 @@ hvm_emulate_cmpxchg(enum x86_segment seg
unsigned long addr, old, new;
int rc;
- if ( !is_x86_user_segment(seg) || bytes > sizeof(long) )
+ if ( bytes > sizeof(long) )
return X86EMUL_UNHANDLEABLE;
rc = hvm_translate_linear_addr(
--- a/xen/arch/x86/mm/shadow/private.h
+++ b/xen/arch/x86/mm/shadow/private.h
@@ -740,8 +740,6 @@ const struct x86_emulate_ops *shadow_ini
struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs);
void shadow_continue_emulation(
struct sh_emulate_ctxt *sh_ctxt, struct cpu_user_regs *regs);
-struct segment_register *hvm_get_seg_reg(
- enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt);
#if (SHADOW_OPTIMIZATIONS & SHOPT_VIRTUAL_TLB)
/**************************************************************************/
--- a/xen/include/asm-x86/hvm/emulate.h
+++ b/xen/include/asm-x86/hvm/emulate.h
@@ -13,6 +13,7 @@
#define __ASM_X86_HVM_EMULATE_H__
#include <xen/config.h>
+#include <xen/err.h>
#include <asm/hvm/hvm.h>
#include <asm/x86_emulate.h>

View file

@ -1,173 +0,0 @@
x86emul: honor guest CR0.TS and CR0.EM
We must not emulate any instructions accessing respective registers
when either of these flags is set in the guest view of the register, or
else we may do so on data not belonging to the guest's current task.
Being architecturally required behavior, the logic gets placed in the
instruction emulator instead of hvmemul_get_fpu(). It should be noted,
though, that hvmemul_get_fpu() being the only current handler for the
get_fpu() callback, we don't have an active problem with CR4: Both
CR4.OSFXSR and CR4.OSXSAVE get handled as necessary by that function.
This is XSA-190.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
---
v4: Only raise #NM on FWAIT when CR0.TS and CR0.MP are set.
v3: Correct which exception to raise upon set CR0.EM.
v2: Require the read_cr hook to be set, which then requires a change to
the test code too.
---
The change to xen/arch/x86/hvm/emulate.c isn't strictly needed for
fixing the security issue, but the patch would be rather incomplete
without.
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -158,6 +158,22 @@ static inline uint64_t xgetbv(uint32_t x
(ebx & (1U << 5)) != 0; \
})
+static int read_cr(
+ unsigned int reg,
+ unsigned long *val,
+ struct x86_emulate_ctxt *ctxt)
+{
+ /* Fake just enough state for the emulator's _get_fpu() to be happy. */
+ switch ( reg )
+ {
+ case 0:
+ *val = 0x00000001; /* PE */
+ return X86EMUL_OKAY;
+ }
+
+ return X86EMUL_UNHANDLEABLE;
+}
+
int get_fpu(
void (*exception_callback)(void *, struct cpu_user_regs *),
void *exception_callback_arg,
@@ -189,6 +205,7 @@ static struct x86_emulate_ops emulops =
.write = write,
.cmpxchg = cmpxchg,
.cpuid = cpuid,
+ .read_cr = read_cr,
.get_fpu = get_fpu,
};
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -1628,14 +1628,14 @@ static int hvmemul_get_fpu(
switch ( type )
{
case X86EMUL_FPU_fpu:
+ case X86EMUL_FPU_wait:
break;
case X86EMUL_FPU_mmx:
if ( !cpu_has_mmx )
return X86EMUL_UNHANDLEABLE;
break;
case X86EMUL_FPU_xmm:
- if ( (curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_EM) ||
- !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) )
+ if ( !(curr->arch.hvm_vcpu.guest_cr[4] & X86_CR4_OSFXSR) )
return X86EMUL_UNHANDLEABLE;
break;
case X86EMUL_FPU_ymm:
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -420,6 +420,9 @@ typedef union {
/* Control register flags. */
#define CR0_PE (1<<0)
+#define CR0_MP (1<<1)
+#define CR0_EM (1<<2)
+#define CR0_TS (1<<3)
#define CR4_TSD (1<<2)
/* EFLAGS bit definitions. */
@@ -447,6 +450,7 @@ typedef union {
#define EXC_OF 4
#define EXC_BR 5
#define EXC_UD 6
+#define EXC_NM 7
#define EXC_TS 10
#define EXC_NP 11
#define EXC_SS 12
@@ -746,10 +750,45 @@ static void fpu_handle_exception(void *_
regs->eip += fic->insn_bytes;
}
+static int _get_fpu(
+ enum x86_emulate_fpu_type type,
+ struct fpu_insn_ctxt *fic,
+ struct x86_emulate_ctxt *ctxt,
+ const struct x86_emulate_ops *ops)
+{
+ int rc;
+
+ fic->exn_raised = 0;
+
+ fail_if(!ops->get_fpu);
+ rc = ops->get_fpu(fpu_handle_exception, fic, type, ctxt);
+
+ if ( rc == X86EMUL_OKAY )
+ {
+ unsigned long cr0;
+
+ fail_if(!ops->read_cr);
+ rc = ops->read_cr(0, &cr0, ctxt);
+ if ( rc != X86EMUL_OKAY )
+ return rc;
+ if ( cr0 & CR0_EM )
+ {
+ generate_exception_if(type == X86EMUL_FPU_fpu, EXC_NM, -1);
+ generate_exception_if(type == X86EMUL_FPU_mmx, EXC_UD, -1);
+ generate_exception_if(type == X86EMUL_FPU_xmm, EXC_UD, -1);
+ }
+ generate_exception_if((cr0 & CR0_TS) &&
+ (type != X86EMUL_FPU_wait || (cr0 & CR0_MP)),
+ EXC_NM, -1);
+ }
+
+ done:
+ return rc;
+}
+
#define get_fpu(_type, _fic) \
-do{ (_fic)->exn_raised = 0; \
- fail_if(ops->get_fpu == NULL); \
- rc = ops->get_fpu(fpu_handle_exception, _fic, _type, ctxt); \
+do { \
+ rc = _get_fpu(_type, _fic, ctxt, ops); \
if ( rc ) goto done; \
} while (0)
#define _put_fpu() \
@@ -2879,8 +2918,14 @@ x86_emulate(
}
case 0x9b: /* wait/fwait */
- emulate_fpu_insn("fwait");
+ {
+ struct fpu_insn_ctxt fic = { .insn_bytes = 1 };
+
+ get_fpu(X86EMUL_FPU_wait, &fic);
+ asm volatile ( "fwait" ::: "memory" );
+ put_fpu(&fic);
break;
+ }
case 0x9c: /* pushf */
src.val = _regs.eflags;
--- a/xen/arch/x86/x86_emulate/x86_emulate.h
+++ b/xen/arch/x86/x86_emulate/x86_emulate.h
@@ -115,6 +115,7 @@ struct __packed segment_register {
/* FPU sub-types which may be requested via ->get_fpu(). */
enum x86_emulate_fpu_type {
X86EMUL_FPU_fpu, /* Standard FPU coprocessor instruction set */
+ X86EMUL_FPU_wait, /* WAIT/FWAIT instruction */
X86EMUL_FPU_mmx, /* MMX instruction set (%mm0-%mm7) */
X86EMUL_FPU_xmm, /* SSE instruction set (%xmm0-%xmm7/15) */
X86EMUL_FPU_ymm /* AVX/XOP instruction set (%ymm0-%ymm7/15) */