xen: patches for musl support and XSA-154, XSA-155 and XSA-170 (from Alpine).

This commit is contained in:
Juan RP 2016-04-23 08:07:56 +02:00
parent 5b8d518a38
commit 6b6fe3c3f1
11 changed files with 3750 additions and 5 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,23 @@
/* 32 bit int types */
#ifndef STDINT_LOCAL_H
#define STDINT_LOCAL_H
typedef signed char int8_t;
typedef short int int16_t;
typedef int int32_t;
# if defined(__x86_64__)
typedef long int int64_t;
#else
typedef long long int int64_t;
#endif
/* Unsigned. */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
# if defined(__x86_64__)
typedef unsigned long int uint64_t;
#else
typedef unsigned long long int uint64_t;
#endif
#endif

View file

@ -0,0 +1,189 @@
musl's stdint does not support gcc -m32 so we need to make sure that we
don't use system's stdint.h. We ship a stdind_local.h and make sure that
we use that instead
https://bugs.alpinelinux.org/issues/3308
diff --git a/tools/firmware/Rules.mk b/tools/firmware/Rules.mk
index 26bbddc..efad58c 100644
--- a/tools/firmware/Rules.mk
+++ b/tools/firmware/Rules.mk
@@ -12,6 +12,7 @@ CFLAGS += -DNDEBUG
endif
CFLAGS += -Werror
+CFLAGS += -I$(XEN_ROOT)/tools/firmware
$(call cc-options-add,CFLAGS,CC,$(EMBEDDED_EXTRA_CFLAGS))
diff --git a/tools/firmware/hvmloader/32bitbios_support.c b/tools/firmware/hvmloader/32bitbios_support.c
index fe770a3..cdab677 100644
--- a/tools/firmware/hvmloader/32bitbios_support.c
+++ b/tools/firmware/hvmloader/32bitbios_support.c
@@ -21,8 +21,8 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
-#include <inttypes.h>
-#include <elf.h>
+#include <stdint_local.h>
+#include <elf_local.h>
#ifdef __sun__
#include <sys/machelf.h>
#endif
diff --git a/tools/firmware/hvmloader/acpi/acpi2_0.h b/tools/firmware/hvmloader/acpi/acpi2_0.h
index 7b22d80..413c930 100644
--- a/tools/firmware/hvmloader/acpi/acpi2_0.h
+++ b/tools/firmware/hvmloader/acpi/acpi2_0.h
@@ -18,7 +18,7 @@
#ifndef _ACPI_2_0_H_
#define _ACPI_2_0_H_
-#include <stdint.h>
+#include <stdint_local.h>
#include <xen/xen.h>
#include <xen/hvm/ioreq.h>
diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h
index b838cf9..33d48b3 100644
--- a/tools/firmware/hvmloader/config.h
+++ b/tools/firmware/hvmloader/config.h
@@ -1,7 +1,7 @@
#ifndef __HVMLOADER_CONFIG_H__
#define __HVMLOADER_CONFIG_H__
-#include <stdint.h>
+#include <stdint_local.h>
enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt };
extern enum virtual_vga virtual_vga;
diff --git a/tools/firmware/hvmloader/hypercall.h b/tools/firmware/hvmloader/hypercall.h
index 5368c30..c57bc86 100644
--- a/tools/firmware/hvmloader/hypercall.h
+++ b/tools/firmware/hvmloader/hypercall.h
@@ -31,7 +31,7 @@
#ifndef __HVMLOADER_HYPERCALL_H__
#define __HVMLOADER_HYPERCALL_H__
-#include <stdint.h>
+#include <stdint_local.h>
#include <xen/xen.h>
#include "config.h"
diff --git a/tools/firmware/hvmloader/mp_tables.c b/tools/firmware/hvmloader/mp_tables.c
index fd636a0..b3b703e 100644
--- a/tools/firmware/hvmloader/mp_tables.c
+++ b/tools/firmware/hvmloader/mp_tables.c
@@ -28,7 +28,7 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
-#include <stdint.h>
+#include <stdint_local.h>
#include "config.h"
/* number of non-processor MP table entries */
diff --git a/tools/firmware/hvmloader/option_rom.h b/tools/firmware/hvmloader/option_rom.h
index 0fefe08..66a93bc 100644
--- a/tools/firmware/hvmloader/option_rom.h
+++ b/tools/firmware/hvmloader/option_rom.h
@@ -1,7 +1,7 @@
#ifndef __HVMLOADER_OPTION_ROM_H__
#define __HVMLOADER_OPTION_ROM_H__
-#include <stdint.h>
+#include <stdint_local.h>
struct option_rom_header {
uint8_t signature[2]; /* "\x55\xaa" */
diff --git a/tools/firmware/hvmloader/pir_types.h b/tools/firmware/hvmloader/pir_types.h
index 6e50822..6134b01 100644
--- a/tools/firmware/hvmloader/pir_types.h
+++ b/tools/firmware/hvmloader/pir_types.h
@@ -24,7 +24,7 @@
#ifndef PIR_TYPES_H
#define PIR_TYPES_H
-#include <stdint.h>
+#include <stdint_local.h>
#define NR_PIR_SLOTS 6
diff --git a/tools/firmware/hvmloader/smbios.c b/tools/firmware/hvmloader/smbios.c
index 4d3d692..60d144d 100644
--- a/tools/firmware/hvmloader/smbios.c
+++ b/tools/firmware/hvmloader/smbios.c
@@ -20,7 +20,7 @@
* Authors: Andrew D. Ball <aball@us.ibm.com>
*/
-#include <stdint.h>
+#include <stdint_local.h>
#include <xen/xen.h>
#include <xen/version.h>
#include "smbios_types.h"
diff --git a/tools/firmware/hvmloader/smbios_types.h b/tools/firmware/hvmloader/smbios_types.h
index ff36564..1b61d9a 100644
--- a/tools/firmware/hvmloader/smbios_types.h
+++ b/tools/firmware/hvmloader/smbios_types.h
@@ -26,7 +26,7 @@
#ifndef SMBIOS_TYPES_H
#define SMBIOS_TYPES_H
-#include <stdint.h>
+#include <stdint_local.h>
/* SMBIOS entry point -- must be written to a 16-bit aligned address
between 0xf0000 and 0xfffff.
diff --git a/tools/firmware/hvmloader/util.c b/tools/firmware/hvmloader/util.c
index 80d822f..671d8cd 100644
--- a/tools/firmware/hvmloader/util.c
+++ b/tools/firmware/hvmloader/util.c
@@ -22,7 +22,7 @@
#include "config.h"
#include "hypercall.h"
#include "ctype.h"
-#include <stdint.h>
+#include <stdint_local.h>
#include <xen/xen.h>
#include <xen/memory.h>
#include <xen/sched.h>
diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h
index a70e4aa..a8a2628 100644
--- a/tools/firmware/hvmloader/util.h
+++ b/tools/firmware/hvmloader/util.h
@@ -2,7 +2,7 @@
#define __HVMLOADER_UTIL_H__
#include <stdarg.h>
-#include <stdint.h>
+#include <stdint_local.h>
#include <stddef.h>
#include <xen/xen.h>
#include <xen/hvm/hvm_info_table.h>
diff --git a/tools/firmware/rombios/32bit/pmm.c b/tools/firmware/rombios/32bit/pmm.c
index 4a279ca..b90b813 100644
--- a/tools/firmware/rombios/32bit/pmm.c
+++ b/tools/firmware/rombios/32bit/pmm.c
@@ -63,7 +63,7 @@
* }
*/
-#include <stdint.h>
+#include <stdint_local.h>
#include <stddef.h>
#include "config.h"
#include "e820.h"
diff --git a/tools/firmware/rombios/32bit/util.c b/tools/firmware/rombios/32bit/util.c
index a47bb71..777f742 100644
--- a/tools/firmware/rombios/32bit/util.c
+++ b/tools/firmware/rombios/32bit/util.c
@@ -18,7 +18,7 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*/
#include <stdarg.h>
-#include <stdint.h>
+#include <stdint_local.h>
#include "rombios_compat.h"
#include "util.h"

View file

@ -0,0 +1,85 @@
--- xen-4.3.1.orig/m4/ptyfuncs.m4
+++ xen-4.3.1/m4/ptyfuncs.m4
@@ -22,7 +22,6 @@
#endif
int main(void) {
openpty(0,0,0,0,0);
- login_tty(0);
}
])],[
break
--- xen-4.3.1.orig/tools/libxl/libxl_bootloader.c
+++ xen-4.3.1/tools/libxl/libxl_bootloader.c
@@ -85,6 +85,21 @@
/*----- synchronous subroutines -----*/
+static int setup_console_tty(int fd)
+{
+ (void) setsid();
+#ifdef TIOCSCTTY
+ if (ioctl(fd, TIOCSCTTY, (char *)NULL) == -1)
+ return (-1);
+#endif
+ (void) dup2(fd, 0);
+ (void) dup2(fd, 1);
+ (void) dup2(fd, 2);
+ if (fd > 2)
+ (void) close(fd);
+ return (0);
+}
+
static int setup_xenconsoled_pty(libxl__egc *egc, libxl__bootloader_state *bl,
char *slave_path, size_t slave_path_len)
{
@@ -548,7 +563,7 @@
if (!pid) {
/* child */
- r = login_tty(libxl__carefd_fd(bl->ptys[0].slave));
+ r = setup_console_tty(libxl__carefd_fd(bl->ptys[0].slave));
if (r) { LOGE(ERROR, "login_tty failed"); exit(-1); }
libxl__exec(gc, -1, -1, -1, bl->args[0], (char **) bl->args, env);
exit(-1);
--- xen-4.3.1.orig/tools/firmware/hvmloader/acpi/acpi2_0.h
+++ xen-4.3.1/tools/firmware/hvmloader/acpi/acpi2_0.h
@@ -366,7 +366,7 @@
/*
* Table Signatures.
*/
-#define ACPI_2_0_RSDP_SIGNATURE ASCII64('R','S','D',' ','P','T','R',' ')
+#define ACPI_2_0_RSDP_SIGNATURE 0x2052545020445352LL /* "RSD PTR " */
#define ACPI_2_0_FACS_SIGNATURE ASCII32('F','A','C','S')
#define ACPI_2_0_FADT_SIGNATURE ASCII32('F','A','C','P')
#define ACPI_2_0_MADT_SIGNATURE ASCII32('A','P','I','C')
--- xen-4.3.1.orig/tools/blktap2/vhd/lib/libvhd-journal.c
+++ xen-4.3.1/tools/blktap2/vhd/lib/libvhd-journal.c
@@ -30,6 +30,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
+#include <sys/stat.h>
#include "atomicio.h"
#include "libvhd-journal.h"
--- xen-4.3.1.orig/tools/blktap2/include/atomicio.h
+++ xen-4.3.1/tools/blktap2/include/atomicio.h
@@ -25,6 +25,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#include <sys/types.h>
+
/*
* Ensure all of data on socket comes through. f==read || f==vwrite
*/
--- xen-4.3.1.orig/tools/blktap2/drivers/block-remus.c
+++ xen-4.3.1/tools/blktap2/drivers/block-remus.c
@@ -54,7 +54,6 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/param.h>
-#include <sys/sysctl.h>
#include <unistd.h>
#include <sys/stat.h>

View file

@ -0,0 +1,10 @@
--- a/tools/Makefile.orig
+++ b/tools/Makefile
@@ -202,6 +202,7 @@
--localstatedir=/var \
--disable-kvm \
--disable-docs \
+ --with-coroutine=gthread \
--disable-guest-agent \
--python=$(PYTHON) \
$(IOEMU_CONFIGURE_CROSS); \

View file

@ -0,0 +1,359 @@
x86: enforce consistent cachability of MMIO mappings
We've been told by Intel that inconsistent cachability between
multiple mappings of the same page can affect system stability only
when the affected page is an MMIO one. Since the stale data issue is
of no relevance to the hypervisor (since all guest memory accesses go
through proper accessors and validation), handling of RAM pages
remains unchanged here. Any MMIO mapped by domains however needs to be
done consistently (all cachable mappings or all uncachable ones), in
order to avoid Machine Check exceptions. Since converting existing
cachable mappings to uncachable (at the time an uncachable mapping
gets established) would in the PV case require tracking all mappings,
allow MMIO to only get mapped uncachable (UC, UC-, or WC).
This also implies that in the PV case we mustn't use the L1 PTE update
fast path when cachability flags get altered.
Since in the HVM case at least for now we want to continue honoring
pinned cachability attributes for pages not mapped by the hypervisor,
special case handling of r/o MMIO pages (forcing UC) gets added there.
Arguably the counterpart change to p2m-pt.c may not be necessary, since
UC- (which already gets enforced there) is probably strict enough.
Note that the shadow code changes include fixing the write protection
of r/o MMIO ranges: shadow_l1e_remove_flags() and its siblings, other
than l1e_remove_flags() and alike, return the new PTE (and hence
ignoring their return values makes them no-ops).
This is CVE-2016-2270 / XSA-154.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/docs/misc/xen-command-line.markdown
+++ b/docs/misc/xen-command-line.markdown
@@ -1080,6 +1080,15 @@ limit is ignored by Xen.
Specify if the MMConfig space should be enabled.
+### mmio-relax
+> `= <boolean> | all`
+
+> Default: `false`
+
+By default, domains may not create cached mappings to MMIO regions.
+This option relaxes the check for Domain 0 (or when using `all`, all PV
+domains), to permit the use of cacheable MMIO mappings.
+
### msi
> `= <boolean>`
--- a/xen/arch/x86/hvm/mtrr.c
+++ b/xen/arch/x86/hvm/mtrr.c
@@ -807,8 +807,17 @@ int epte_get_entry_emt(struct domain *d,
if ( v->domain != d )
v = d->vcpu ? d->vcpu[0] : NULL;
- if ( !mfn_valid(mfn_x(mfn)) )
+ if ( !mfn_valid(mfn_x(mfn)) ||
+ rangeset_contains_range(mmio_ro_ranges, mfn_x(mfn),
+ mfn_x(mfn) + (1UL << order) - 1) )
+ {
+ *ipat = 1;
return MTRR_TYPE_UNCACHABLE;
+ }
+
+ if ( rangeset_overlaps_range(mmio_ro_ranges, mfn_x(mfn),
+ mfn_x(mfn) + (1UL << order) - 1) )
+ return -1;
switch ( hvm_get_mem_pinned_cacheattr(d, gfn, order, &type) )
{
--- a/xen/arch/x86/mm/p2m-pt.c
+++ b/xen/arch/x86/mm/p2m-pt.c
@@ -107,6 +107,8 @@ static unsigned long p2m_type_to_flags(p
case p2m_mmio_direct:
if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn_x(mfn)) )
flags |= _PAGE_RW;
+ else
+ flags |= _PAGE_PWT;
return flags | P2M_BASE_FLAGS | _PAGE_PCD;
}
}
--- a/xen/arch/x86/mm/shadow/multi.c
+++ b/xen/arch/x86/mm/shadow/multi.c
@@ -519,6 +519,7 @@ _sh_propagate(struct vcpu *v,
gfn_t target_gfn = guest_l1e_get_gfn(guest_entry);
u32 pass_thru_flags;
u32 gflags, sflags;
+ bool_t mmio_mfn;
/* We don't shadow PAE l3s */
ASSERT(GUEST_PAGING_LEVELS > 3 || level != 3);
@@ -559,7 +560,10 @@ _sh_propagate(struct vcpu *v,
// mfn means that we can not usefully shadow anything, and so we
// return early.
//
- if ( !mfn_valid(target_mfn)
+ mmio_mfn = !mfn_valid(target_mfn)
+ || (level == 1
+ && page_get_owner(mfn_to_page(target_mfn)) == dom_io);
+ if ( mmio_mfn
&& !(level == 1 && (!shadow_mode_refcounts(d)
|| p2mt == p2m_mmio_direct)) )
{
@@ -577,7 +581,7 @@ _sh_propagate(struct vcpu *v,
_PAGE_RW | _PAGE_PRESENT);
if ( guest_supports_nx(v) )
pass_thru_flags |= _PAGE_NX_BIT;
- if ( !shadow_mode_refcounts(d) && !mfn_valid(target_mfn) )
+ if ( level == 1 && !shadow_mode_refcounts(d) && mmio_mfn )
pass_thru_flags |= _PAGE_PAT | _PAGE_PCD | _PAGE_PWT;
sflags = gflags & pass_thru_flags;
@@ -676,10 +680,14 @@ _sh_propagate(struct vcpu *v,
}
/* Read-only memory */
- if ( p2m_is_readonly(p2mt) ||
- (p2mt == p2m_mmio_direct &&
- rangeset_contains_singleton(mmio_ro_ranges, mfn_x(target_mfn))) )
+ if ( p2m_is_readonly(p2mt) )
sflags &= ~_PAGE_RW;
+ else if ( p2mt == p2m_mmio_direct &&
+ rangeset_contains_singleton(mmio_ro_ranges, mfn_x(target_mfn)) )
+ {
+ sflags &= ~(_PAGE_RW | _PAGE_PAT);
+ sflags |= _PAGE_PCD | _PAGE_PWT;
+ }
// protect guest page tables
//
@@ -1185,22 +1193,28 @@ static int shadow_set_l1e(struct domain
&& !sh_l1e_is_magic(new_sl1e) )
{
/* About to install a new reference */
- if ( shadow_mode_refcounts(d) ) {
+ if ( shadow_mode_refcounts(d) )
+ {
+#define PAGE_FLIPPABLE (_PAGE_RW | _PAGE_PWT | _PAGE_PCD | _PAGE_PAT)
+ int rc;
+
TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_SHADOW_L1_GET_REF);
- switch ( shadow_get_page_from_l1e(new_sl1e, d, new_type) )
+ switch ( rc = shadow_get_page_from_l1e(new_sl1e, d, new_type) )
{
default:
/* Doesn't look like a pagetable. */
flags |= SHADOW_SET_ERROR;
new_sl1e = shadow_l1e_empty();
break;
- case 1:
- shadow_l1e_remove_flags(new_sl1e, _PAGE_RW);
+ case PAGE_FLIPPABLE & -PAGE_FLIPPABLE ... PAGE_FLIPPABLE:
+ ASSERT(!(rc & ~PAGE_FLIPPABLE));
+ new_sl1e = shadow_l1e_flip_flags(new_sl1e, rc);
/* fall through */
case 0:
shadow_vram_get_l1e(new_sl1e, sl1e, sl1mfn, d);
break;
}
+#undef PAGE_FLIPPABLE
}
}
--- a/xen/arch/x86/mm/shadow/types.h
+++ b/xen/arch/x86/mm/shadow/types.h
@@ -99,6 +99,9 @@ static inline u32 shadow_l4e_get_flags(s
static inline shadow_l1e_t
shadow_l1e_remove_flags(shadow_l1e_t sl1e, u32 flags)
{ l1e_remove_flags(sl1e, flags); return sl1e; }
+static inline shadow_l1e_t
+shadow_l1e_flip_flags(shadow_l1e_t sl1e, u32 flags)
+{ l1e_flip_flags(sl1e, flags); return sl1e; }
static inline shadow_l1e_t shadow_l1e_empty(void)
{ return l1e_empty(); }
--- a/xen/arch/x86/mm.c
+++ b/xen/arch/x86/mm.c
@@ -178,6 +178,18 @@ static uint32_t base_disallow_mask;
is_pv_domain(d)) ? \
L1_DISALLOW_MASK : (L1_DISALLOW_MASK & ~PAGE_CACHE_ATTRS))
+static s8 __read_mostly opt_mmio_relax;
+static void __init parse_mmio_relax(const char *s)
+{
+ if ( !*s )
+ opt_mmio_relax = 1;
+ else
+ opt_mmio_relax = parse_bool(s);
+ if ( opt_mmio_relax < 0 && strcmp(s, "all") )
+ opt_mmio_relax = 0;
+}
+custom_param("mmio-relax", parse_mmio_relax);
+
static void __init init_frametable_chunk(void *start, void *end)
{
unsigned long s = (unsigned long)start;
@@ -799,10 +811,7 @@ get_page_from_l1e(
if ( !mfn_valid(mfn) ||
(real_pg_owner = page_get_owner_and_reference(page)) == dom_io )
{
-#ifndef NDEBUG
- const unsigned long *ro_map;
- unsigned int seg, bdf;
-#endif
+ int flip = 0;
/* Only needed the reference to confirm dom_io ownership. */
if ( mfn_valid(mfn) )
@@ -836,24 +845,55 @@ get_page_from_l1e(
return -EINVAL;
}
- if ( !(l1f & _PAGE_RW) ||
- !rangeset_contains_singleton(mmio_ro_ranges, mfn) )
- return 0;
+ if ( !rangeset_contains_singleton(mmio_ro_ranges, mfn) )
+ {
+ /* MMIO pages must not be mapped cachable unless requested so. */
+ switch ( opt_mmio_relax )
+ {
+ case 0:
+ break;
+ case 1:
+ if ( is_hardware_domain(l1e_owner) )
+ case -1:
+ return 0;
+ default:
+ ASSERT_UNREACHABLE();
+ }
+ }
+ else if ( l1f & _PAGE_RW )
+ {
#ifndef NDEBUG
- if ( !pci_mmcfg_decode(mfn, &seg, &bdf) ||
- ((ro_map = pci_get_ro_map(seg)) != NULL &&
- test_bit(bdf, ro_map)) )
- printk(XENLOG_G_WARNING
- "d%d: Forcing read-only access to MFN %lx\n",
- l1e_owner->domain_id, mfn);
- else
- rangeset_report_ranges(mmio_ro_ranges, 0, ~0UL,
- print_mmio_emul_range,
- &(struct mmio_emul_range_ctxt){
- .d = l1e_owner,
- .mfn = mfn });
+ const unsigned long *ro_map;
+ unsigned int seg, bdf;
+
+ if ( !pci_mmcfg_decode(mfn, &seg, &bdf) ||
+ ((ro_map = pci_get_ro_map(seg)) != NULL &&
+ test_bit(bdf, ro_map)) )
+ printk(XENLOG_G_WARNING
+ "d%d: Forcing read-only access to MFN %lx\n",
+ l1e_owner->domain_id, mfn);
+ else
+ rangeset_report_ranges(mmio_ro_ranges, 0, ~0UL,
+ print_mmio_emul_range,
+ &(struct mmio_emul_range_ctxt){
+ .d = l1e_owner,
+ .mfn = mfn });
#endif
- return 1;
+ flip = _PAGE_RW;
+ }
+
+ switch ( l1f & PAGE_CACHE_ATTRS )
+ {
+ case 0: /* WB */
+ flip |= _PAGE_PWT | _PAGE_PCD;
+ break;
+ case _PAGE_PWT: /* WT */
+ case _PAGE_PWT | _PAGE_PAT: /* WP */
+ flip |= _PAGE_PCD | (l1f & _PAGE_PAT);
+ break;
+ }
+
+ return flip;
}
if ( unlikely( (real_pg_owner != pg_owner) &&
@@ -1243,8 +1283,9 @@ static int alloc_l1_table(struct page_in
goto fail;
case 0:
break;
- case 1:
- l1e_remove_flags(pl1e[i], _PAGE_RW);
+ case _PAGE_RW ... _PAGE_RW | PAGE_CACHE_ATTRS:
+ ASSERT(!(ret & ~(_PAGE_RW | PAGE_CACHE_ATTRS)));
+ l1e_flip_flags(pl1e[i], ret);
break;
}
@@ -1759,8 +1800,9 @@ static int mod_l1_entry(l1_pgentry_t *pl
return -EINVAL;
}
- /* Fast path for identical mapping, r/w and presence. */
- if ( !l1e_has_changed(ol1e, nl1e, _PAGE_RW | _PAGE_PRESENT) )
+ /* Fast path for identical mapping, r/w, presence, and cachability. */
+ if ( !l1e_has_changed(ol1e, nl1e,
+ PAGE_CACHE_ATTRS | _PAGE_RW | _PAGE_PRESENT) )
{
adjust_guest_l1e(nl1e, pt_dom);
if ( UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, pt_vcpu,
@@ -1783,8 +1825,9 @@ static int mod_l1_entry(l1_pgentry_t *pl
return rc;
case 0:
break;
- case 1:
- l1e_remove_flags(nl1e, _PAGE_RW);
+ case _PAGE_RW ... _PAGE_RW | PAGE_CACHE_ATTRS:
+ ASSERT(!(rc & ~(_PAGE_RW | PAGE_CACHE_ATTRS)));
+ l1e_flip_flags(nl1e, rc);
rc = 0;
break;
}
@@ -5000,6 +5043,7 @@ static int ptwr_emulated_update(
l1_pgentry_t pte, ol1e, nl1e, *pl1e;
struct vcpu *v = current;
struct domain *d = v->domain;
+ int ret;
/* Only allow naturally-aligned stores within the original %cr2 page. */
if ( unlikely(((addr^ptwr_ctxt->cr2) & PAGE_MASK) || (addr & (bytes-1))) )
@@ -5047,7 +5091,7 @@ static int ptwr_emulated_update(
/* Check the new PTE. */
nl1e = l1e_from_intpte(val);
- switch ( get_page_from_l1e(nl1e, d, d) )
+ switch ( ret = get_page_from_l1e(nl1e, d, d) )
{
default:
if ( is_pv_32bit_domain(d) && (bytes == 4) && (unaligned_addr & 4) &&
@@ -5071,8 +5115,9 @@ static int ptwr_emulated_update(
break;
case 0:
break;
- case 1:
- l1e_remove_flags(nl1e, _PAGE_RW);
+ case _PAGE_RW ... _PAGE_RW | PAGE_CACHE_ATTRS:
+ ASSERT(!(ret & ~(_PAGE_RW | PAGE_CACHE_ATTRS)));
+ l1e_flip_flags(nl1e, ret);
break;
}
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -157,6 +157,9 @@ static inline l4_pgentry_t l4e_from_padd
#define l3e_remove_flags(x, flags) ((x).l3 &= ~put_pte_flags(flags))
#define l4e_remove_flags(x, flags) ((x).l4 &= ~put_pte_flags(flags))
+/* Flip flags in an existing L1 PTE. */
+#define l1e_flip_flags(x, flags) ((x).l1 ^= put_pte_flags(flags))
+
/* Check if a pte's page mapping or significant access flags have changed. */
#define l1e_has_changed(x,y,flags) \
( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags(flags))) )

View file

@ -0,0 +1,56 @@
From 12b11658a9d6a654a1e7acbf2f2d56ce9a396c86 Mon Sep 17 00:00:00 2001
From: David Vrabel <david.vrabel@citrix.com>
Date: Fri, 20 Nov 2015 11:59:05 -0500
Subject: [PATCH 1/3] xen: Add RING_COPY_REQUEST()
Using RING_GET_REQUEST() on a shared ring is easy to use incorrectly
(i.e., by not considering that the other end may alter the data in the
shared ring while it is being inspected). Safe usage of a request
generally requires taking a local copy.
Provide a RING_COPY_REQUEST() macro to use instead of
RING_GET_REQUEST() and an open-coded memcpy(). This takes care of
ensuring that the copy is done correctly regardless of any possible
compiler optimizations.
Use a volatile source to prevent the compiler from reordering or
omitting the copy.
This is part of XSA155.
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
v2: Add comment about GCC bug.
---
xen/include/public/io/ring.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/xen/include/public/io/ring.h b/xen/include/public/io/ring.h
index ba9401b..801c0da 100644
--- a/xen/include/public/io/ring.h
+++ b/xen/include/public/io/ring.h
@@ -212,6 +212,20 @@ typedef struct __name##_back_ring __name##_back_ring_t
#define RING_GET_REQUEST(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].req))
+/*
+ * Get a local copy of a request.
+ *
+ * Use this in preference to RING_GET_REQUEST() so all processing is
+ * done on a local copy that cannot be modified by the other end.
+ *
+ * Note that https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145 may cause this
+ * to be ineffective where _req is a struct which consists of only bitfields.
+ */
+#define RING_COPY_REQUEST(_r, _idx, _req) do { \
+ /* Use volatile to force the copy into _req. */ \
+ *(_req) = *(volatile typeof(_req))RING_GET_REQUEST(_r, _idx); \
+} while (0)
+
#define RING_GET_RESPONSE(_r, _idx) \
(&((_r)->sring->ring[((_idx) & (RING_SIZE(_r) - 1))].rsp))
--
2.1.0

View file

@ -0,0 +1,75 @@
From 851ffb4eea917e2708c912291dea4d133026c0ac Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Fri, 20 Nov 2015 12:16:02 -0500
Subject: [PATCH 2/3] blktap2: Use RING_COPY_REQUEST
Instead of RING_GET_REQUEST. Using a local copy of the
ring (and also with proper memory barriers) will mean
we can do not have to worry about the compiler optimizing
the code and doing a double-fetch in the shared memory space.
This is part of XSA155.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
v2: Fix compile issues with tapdisk-vbd
---
tools/blktap2/drivers/block-log.c | 3 ++-
tools/blktap2/drivers/tapdisk-vbd.c | 8 ++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/tools/blktap2/drivers/block-log.c b/tools/blktap2/drivers/block-log.c
index 5330cdc..5f3bd35 100644
--- a/tools/blktap2/drivers/block-log.c
+++ b/tools/blktap2/drivers/block-log.c
@@ -494,11 +494,12 @@ static int ctl_kick(struct tdlog_state* s, int fd)
reqstart = s->bring.req_cons;
reqend = s->sring->req_prod;
+ xen_mb();
BDPRINTF("ctl: ring kicked (start = %u, end = %u)", reqstart, reqend);
while (reqstart != reqend) {
/* XXX actually submit these! */
- memcpy(&req, RING_GET_REQUEST(&s->bring, reqstart), sizeof(req));
+ RING_COPY_REQUEST(&s->bring, reqstart, &req);
BDPRINTF("ctl: read request %"PRIu64":%u", req.sector, req.count);
s->bring.req_cons = ++reqstart;
diff --git a/tools/blktap2/drivers/tapdisk-vbd.c b/tools/blktap2/drivers/tapdisk-vbd.c
index 6d1d94a..89ef9ed 100644
--- a/tools/blktap2/drivers/tapdisk-vbd.c
+++ b/tools/blktap2/drivers/tapdisk-vbd.c
@@ -1555,7 +1555,7 @@ tapdisk_vbd_pull_ring_requests(td_vbd_t *vbd)
int idx;
RING_IDX rp, rc;
td_ring_t *ring;
- blkif_request_t *req;
+ blkif_request_t req;
td_vbd_request_t *vreq;
ring = &vbd->ring;
@@ -1566,16 +1566,16 @@ tapdisk_vbd_pull_ring_requests(td_vbd_t *vbd)
xen_rmb();
for (rc = ring->fe_ring.req_cons; rc != rp; rc++) {
- req = RING_GET_REQUEST(&ring->fe_ring, rc);
+ RING_COPY_REQUEST(&ring->fe_ring, rc, &req);
++ring->fe_ring.req_cons;
- idx = req->id;
+ idx = req.id;
vreq = &vbd->request_list[idx];
ASSERT(list_empty(&vreq->next));
ASSERT(vreq->secs_pending == 0);
- memcpy(&vreq->req, req, sizeof(blkif_request_t));
+ memcpy(&vreq->req, &req, sizeof(blkif_request_t));
vbd->received++;
vreq->vbd = vbd;
--
2.1.4

View file

@ -0,0 +1,41 @@
From c1fce65e2b720684ea6ba76ae59921542bd154bb Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Fri, 20 Nov 2015 12:22:14 -0500
Subject: [PATCH 3/3] libvchan: Read prod/cons only once.
We must ensure that the prod/cons are only read once and that
the compiler won't try to optimize the reads. That is split
the read of these in multiple instructions influencing later
branch code. As such insert barriers when fetching the cons
and prod index.
This is part of XSA155.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
tools/libvchan/io.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tools/libvchan/io.c b/tools/libvchan/io.c
index 8a9629b..381cc05 100644
--- a/tools/libvchan/io.c
+++ b/tools/libvchan/io.c
@@ -117,6 +117,7 @@ static inline int send_notify(struct libxenvchan *ctrl, uint8_t bit)
static inline int raw_get_data_ready(struct libxenvchan *ctrl)
{
uint32_t ready = rd_prod(ctrl) - rd_cons(ctrl);
+ xen_mb(); /* Ensure 'ready' is read only once. */
if (ready > rd_ring_size(ctrl))
/* We have no way to return errors. Locking up the ring is
* better than the alternatives. */
@@ -158,6 +159,7 @@ int libxenvchan_data_ready(struct libxenvchan *ctrl)
static inline int raw_get_buffer_space(struct libxenvchan *ctrl)
{
uint32_t ready = wr_ring_size(ctrl) - (wr_prod(ctrl) - wr_cons(ctrl));
+ xen_mb(); /* Ensure 'ready' is read only once. */
if (ready > wr_ring_size(ctrl))
/* We have no way to return errors. Locking up the ring is
* better than the alternatives. */
--
2.1.0

View file

@ -0,0 +1,79 @@
x86/VMX: sanitize rIP before re-entering guest
... to prevent guest user mode arranging for a guest crash (due to
failed VM entry). (On the AMD system I checked, hardware is doing
exactly the canonicalization being added here.)
Note that fixing this in an architecturally correct way would be quite
a bit more involved: Making the x86 instruction emulator check all
branch targets for validity, plus dealing with invalid rIP resulting
from update_guest_eip() or incoming directly during a VM exit. The only
way to get the latter right would be by not having hardware do the
injection.
Note further that there are a two early returns from
vmx_vmexit_handler(): One (through vmx_failed_vmentry()) leads to
domain_crash() anyway, and the other covers real mode only and can
neither occur with a non-canonical rIP nor result in an altered rIP,
so we don't need to force those paths through the checking logic.
This is XSA-170.
Reported-by: 刘令 <liuling-it@360.cn>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
Tested-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -2968,7 +2968,7 @@ static int vmx_handle_apic_write(void)
void vmx_vmexit_handler(struct cpu_user_regs *regs)
{
unsigned long exit_qualification, exit_reason, idtv_info, intr_info = 0;
- unsigned int vector = 0;
+ unsigned int vector = 0, mode;
struct vcpu *v = current;
__vmread(GUEST_RIP, &regs->rip);
@@ -3566,6 +3566,41 @@ void vmx_vmexit_handler(struct cpu_user_
out:
if ( nestedhvm_vcpu_in_guestmode(v) )
nvmx_idtv_handling();
+
+ /*
+ * VM entry will fail (causing the guest to get crashed) if rIP (and
+ * rFLAGS, but we don't have an issue there) doesn't meet certain
+ * criteria. As we must not allow less than fully privileged mode to have
+ * such an effect on the domain, we correct rIP in that case (accepting
+ * this not being architecturally correct behavior, as the injected #GP
+ * fault will then not see the correct [invalid] return address).
+ * And since we know the guest will crash, we crash it right away if it
+ * already is in most privileged mode.
+ */
+ mode = vmx_guest_x86_mode(v);
+ if ( mode == 8 ? !is_canonical_address(regs->rip)
+ : regs->rip != regs->_eip )
+ {
+ struct segment_register ss;
+
+ gprintk(XENLOG_WARNING, "Bad rIP %lx for mode %u\n", regs->rip, mode);
+
+ vmx_get_segment_register(v, x86_seg_ss, &ss);
+ if ( ss.attr.fields.dpl )
+ {
+ __vmread(VM_ENTRY_INTR_INFO, &intr_info);
+ if ( !(intr_info & INTR_INFO_VALID_MASK) )
+ hvm_inject_hw_exception(TRAP_gp_fault, 0);
+ /* Need to fix rIP nevertheless. */
+ if ( mode == 8 )
+ regs->rip = (long)(regs->rip << (64 - VADDR_BITS)) >>
+ (64 - VADDR_BITS);
+ else
+ regs->rip = regs->_eip;
+ }
+ else
+ domain_crash(v->domain);
+ }
}
void vmx_vmenter_helper(const struct cpu_user_regs *regs)

View file

@ -1,7 +1,7 @@
# Template file for 'xen'
pkgname=xen
version=4.6.1
revision=1
revision=2
short_desc="The Xen hypervisor utilities"
maintainer="Juan RP <xtraeme@voidlinux.eu>"
homepage="http://xen.org"
@ -9,16 +9,22 @@ license="GPL-2"
distfiles="http://bits.xensource.com/oss-xen/release/$version/xen-$version.tar.gz"
checksum=44cc2fccba1e147ef4c8da0584ce0f24189c8743de0e3e9a9226da88ddb5f589
only_for_archs="x86_64"
patch_args="-Np1"
only_for_archs="x86_64 x86_64-musl"
hostmakedepends="wget bison perl pkg-config git"
hostmakedepends="automake wget bison perl pkg-config git"
makedepends="
libaio-devel lzo-devel libressl-devel e2fsprogs-devel zlib-devel gnutls-devel
libbluetooth-devel pciutils-devel libX11-devel libXext-devel SDL-devel MesaLib-devel
ncurses-devel liblzma-devel python-devel yajl-devel libuuid-devel libglib-devel
dev86 acpica-utils pixman-devel gcc-multilib"
acpica-utils pixman-devel dev86"
depends="xen-hypervisor"
case "$XBPS_TARGET_MACHINE" in
*-musl) makedepends+=" argp-standalone";;
*) makedepends+=" gcc-multilib";;
esac
make_dirs="
/var/lib/xenstored 755 root root
/var/lib/xen/xenpaging 755 root root
@ -39,12 +45,15 @@ pycompile_module="xen grub"
do_configure() {
rm -f ${XBPS_WRAPPERDIR}/strip
cp ${FILESDIR}/*.h ${wrksrc}/tools/firmware
autoreconf -fi
# Get rid of -Werror
find . -name '*.mk' -o -name 'Make*' | xargs sed -i -e 's/-Werror//g'
unset CC LD AR AS RANLIB CPP CFLAGS CXXFLAGS CPPFLAGS LDFLAGS
./configure ${configure_args}
}
do_build() {
rm -f ${XBPS_WRAPPERDIR}/strip
cd ${wrksrc}
unset CC LD AR AS RANLIB CPP CFLAGS CXXFLAGS CPPFLAGS LDFLAGS
make ${makejobs} DISTDIR=${wrksrc}/${pkgver}-distdir
}