diff options
author | bouyer <bouyer@pkgsrc.org> | 2016-09-08 15:41:01 +0000 |
---|---|---|
committer | bouyer <bouyer@pkgsrc.org> | 2016-09-08 15:41:01 +0000 |
commit | 4ce21eb40a1cd870ea39b679d23ea4652cc5a291 (patch) | |
tree | 95d0d14d76215db39d0580db078bf484b1ff004e /sysutils | |
parent | f815453d5e9c22cf6f01f87512e55d443fcd5c74 (diff) | |
download | pkgsrc-4ce21eb40a1cd870ea39b679d23ea4652cc5a291.tar.gz |
Backport upstream patches for security issues:
XSA-185: x86: Disallow L3 recursive pagetable for 32-bit PV guests
XSA-187: x86 HVM: Overflow of sh_ctxt->seg_reg[]
bump PKGREVISION
Diffstat (limited to 'sysutils')
-rw-r--r-- | sysutils/xenkernel41/Makefile | 4 | ||||
-rw-r--r-- | sysutils/xenkernel41/distinfo | 5 | ||||
-rw-r--r-- | sysutils/xenkernel41/patches/patch-XSA-185 | 37 | ||||
-rw-r--r-- | sysutils/xenkernel41/patches/patch-XSA-187-1 | 44 | ||||
-rw-r--r-- | sysutils/xenkernel41/patches/patch-XSA-187-2 | 152 | ||||
-rw-r--r-- | sysutils/xenkernel42/Makefile | 4 | ||||
-rw-r--r-- | sysutils/xenkernel42/distinfo | 5 | ||||
-rw-r--r-- | sysutils/xenkernel42/patches/patch-XSA-185 | 37 | ||||
-rw-r--r-- | sysutils/xenkernel42/patches/patch-XSA-187-1 | 44 | ||||
-rw-r--r-- | sysutils/xenkernel42/patches/patch-XSA-187-2 | 144 |
10 files changed, 470 insertions, 6 deletions
diff --git a/sysutils/xenkernel41/Makefile b/sysutils/xenkernel41/Makefile index b46eef04714..bdc7ceaf0a2 100644 --- a/sysutils/xenkernel41/Makefile +++ b/sysutils/xenkernel41/Makefile @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.50 2016/07/26 15:59:20 bouyer Exp $ +# $NetBSD: Makefile,v 1.51 2016/09/08 15:41:01 bouyer Exp $ VERSION= 4.1.6.1 DISTNAME= xen-${VERSION} PKGNAME= xenkernel41-${VERSION} -PKGREVISION= 19 +PKGREVISION= 20 CATEGORIES= sysutils MASTER_SITES= http://bits.xensource.com/oss-xen/release/${VERSION}/ diff --git a/sysutils/xenkernel41/distinfo b/sysutils/xenkernel41/distinfo index fd08810b529..f15fe62894f 100644 --- a/sysutils/xenkernel41/distinfo +++ b/sysutils/xenkernel41/distinfo @@ -1,4 +1,4 @@ -$NetBSD: distinfo,v 1.43 2016/07/26 15:59:20 bouyer Exp $ +$NetBSD: distinfo,v 1.44 2016/09/08 15:41:01 bouyer Exp $ SHA1 (xen-4.1.6.1.tar.gz) = e5f15feb0821578817a65ede16110c6eac01abd0 RMD160 (xen-4.1.6.1.tar.gz) = bff11421fc44a26f2cc3156713267abcb36d7a19 @@ -38,6 +38,9 @@ SHA1 (patch-CVE-2015-8339) = e5485ab9e73fa9a63c566505b8de805530ac678e SHA1 (patch-Config.mk) = a43ed1b3304d6383dc093acd128a7f373d0ca266 SHA1 (patch-XSA-166) = 24fccf8e30ccf910a128e5e0365800191a90524c SHA1 (patch-XSA-182) = 70a7a6175a4b87ffaf72cbc5a3932f076efa3f9c +SHA1 (patch-XSA-185) = a2313922aa4dad734b96c80f64fe54eca3c14019 +SHA1 (patch-XSA-187-1) = 55ea0c2d9c7d8d9476a5ab97342ff552be4faf56 +SHA1 (patch-XSA-187-2) = e21b24771fa9417f593b8f6d1550660bbad36b98 SHA1 (patch-xen_Makefile) = d1c7e4860221f93d90818f45a77748882486f92b SHA1 (patch-xen_arch_x86_Rules.mk) = 6b9b4bfa28924f7d3f6c793a389f1a7ac9d228e2 SHA1 (patch-xen_arch_x86_cpu_mcheck_vmce.c) = 5afd01780a13654f1d21bf1562f6431c8370be0b diff --git a/sysutils/xenkernel41/patches/patch-XSA-185 b/sysutils/xenkernel41/patches/patch-XSA-185 new file mode 100644 index 00000000000..b1d13bac5e7 --- /dev/null +++ b/sysutils/xenkernel41/patches/patch-XSA-185 @@ -0,0 +1,37 @@ +$NetBSD: patch-XSA-185,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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 +--- xen/arch/x86/mm.c.orig ++++ 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; diff --git a/sysutils/xenkernel41/patches/patch-XSA-187-1 b/sysutils/xenkernel41/patches/patch-XSA-187-1 new file mode 100644 index 00000000000..6481bcb5ace --- /dev/null +++ b/sysutils/xenkernel41/patches/patch-XSA-187-1 @@ -0,0 +1,44 @@ +$NetBSD: patch-XSA-187-1,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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> + +--- xen/arch/x86/mm/shadow/common.c.orig ++++ 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); + diff --git a/sysutils/xenkernel41/patches/patch-XSA-187-2 b/sysutils/xenkernel41/patches/patch-XSA-187-2 new file mode 100644 index 00000000000..0fa5b0a3cc8 --- /dev/null +++ b/sysutils/xenkernel41/patches/patch-XSA-187-2 @@ -0,0 +1,152 @@ +$NetBSD: patch-XSA-187-2,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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> + +--- xen/include/asm-x86/hvm/emulate.h.orig 2014-09-02 08:22:57.000000000 +0200 ++++ xen/include/asm-x86/hvm/emulate.h 2016-09-08 15:57:32.000000000 +0200 +@@ -13,6 +13,7 @@ + #define __ASM_X86_HVM_EMULATE_H__ + + #include <xen/config.h> ++#include <xen/err.h> + #include <asm/x86_emulate.h> + + struct hvm_emulate_ctxt { +--- xen/arch/x86/hvm/emulate.c.orig 2014-09-02 08:22:57.000000000 +0200 ++++ xen/arch/x86/hvm/emulate.c 2016-09-08 16:01:31.000000000 +0200 +@@ -390,6 +390,8 @@ + *reps = min_t(unsigned long, *reps, 4096); + + 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) ) + { +@@ -777,6 +779,10 @@ + 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; + } +@@ -790,6 +796,9 @@ + 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); + +@@ -1130,10 +1139,17 @@ + } + } + ++/* ++ * 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]; +--- xen/arch/x86/mm/shadow/common.c.orig 2016-09-08 17:15:35.000000000 +0200 ++++ xen/arch/x86/mm/shadow/common.c 2016-09-08 17:29:23.000000000 +0200 +@@ -22,6 +22,7 @@ + */ + + #include <xen/config.h> ++#include <xen/err.h> + #include <xen/types.h> + #include <xen/mm.h> + #include <xen/trace.h> +@@ -116,10 +117,19 @@ + /* x86 emulator support for the shadow code + */ + ++/* ++ * 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 *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; +@@ -136,14 +146,9 @@ + 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); +@@ -245,9 +250,6 @@ + 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); +@@ -275,9 +277,6 @@ + unsigned long addr, old[2], new[2]; + int rc; + +- if ( !is_x86_user_segment(seg) ) +- return X86EMUL_UNHANDLEABLE; +- + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) diff --git a/sysutils/xenkernel42/Makefile b/sysutils/xenkernel42/Makefile index 4d8ec6e9635..2cd1087dbe1 100644 --- a/sysutils/xenkernel42/Makefile +++ b/sysutils/xenkernel42/Makefile @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.22 2016/07/26 15:38:00 bouyer Exp $ +# $NetBSD: Makefile,v 1.23 2016/09/08 15:41:01 bouyer Exp $ VERSION= 4.2.5 DISTNAME= xen-${VERSION} PKGNAME= xenkernel42-${VERSION} -PKGREVISION= 11 +PKGREVISION= 12 CATEGORIES= sysutils MASTER_SITES= http://bits.xensource.com/oss-xen/release/${VERSION}/ diff --git a/sysutils/xenkernel42/distinfo b/sysutils/xenkernel42/distinfo index 3b409cb356f..49081b318a8 100644 --- a/sysutils/xenkernel42/distinfo +++ b/sysutils/xenkernel42/distinfo @@ -1,4 +1,4 @@ -$NetBSD: distinfo,v 1.20 2016/07/26 15:38:00 bouyer Exp $ +$NetBSD: distinfo,v 1.21 2016/09/08 15:41:01 bouyer Exp $ SHA1 (xen-4.2.5.tar.gz) = f42741e4ec174495ace70c4b17a6b9b0e60e798a RMD160 (xen-4.2.5.tar.gz) = 7d4f7f1b32ee541d341a756b1f8da02816438d19 @@ -27,6 +27,9 @@ SHA1 (patch-CVE-2015-8555) = 594f85557efe137fb32a88c0dc589a1318184b66 SHA1 (patch-Config.mk) = a43ed1b3304d6383dc093acd128a7f373d0ca266 SHA1 (patch-XSA-166) = 24fccf8e30ccf910a128e5e0365800191a90524c SHA1 (patch-XSA-182) = f0325a6f7c7cc20c3f11367384628dbe25c90b2d +SHA1 (patch-XSA-185) = a2313922aa4dad734b96c80f64fe54eca3c14019 +SHA1 (patch-XSA-187-1) = 55ea0c2d9c7d8d9476a5ab97342ff552be4faf56 +SHA1 (patch-XSA-187-2) = ed2d384b4cf429443560afbf71b42fb4123a279b SHA1 (patch-xen_Makefile) = e0d1b74518b9675ddc64295d1523ded9a8757c0a SHA1 (patch-xen_arch_x86_Rules.mk) = 6b9b4bfa28924f7d3f6c793a389f1a7ac9d228e2 SHA1 (patch-xen_arch_x86_hvm_hvm.c) = b6bac1d466ba5bc276bc3aea9d4c9df37f2b9b0f diff --git a/sysutils/xenkernel42/patches/patch-XSA-185 b/sysutils/xenkernel42/patches/patch-XSA-185 new file mode 100644 index 00000000000..b1d13bac5e7 --- /dev/null +++ b/sysutils/xenkernel42/patches/patch-XSA-185 @@ -0,0 +1,37 @@ +$NetBSD: patch-XSA-185,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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 +--- xen/arch/x86/mm.c.orig ++++ 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; diff --git a/sysutils/xenkernel42/patches/patch-XSA-187-1 b/sysutils/xenkernel42/patches/patch-XSA-187-1 new file mode 100644 index 00000000000..6481bcb5ace --- /dev/null +++ b/sysutils/xenkernel42/patches/patch-XSA-187-1 @@ -0,0 +1,44 @@ +$NetBSD: patch-XSA-187-1,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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> + +--- xen/arch/x86/mm/shadow/common.c.orig ++++ 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); + diff --git a/sysutils/xenkernel42/patches/patch-XSA-187-2 b/sysutils/xenkernel42/patches/patch-XSA-187-2 new file mode 100644 index 00000000000..18767336c4c --- /dev/null +++ b/sysutils/xenkernel42/patches/patch-XSA-187-2 @@ -0,0 +1,144 @@ +$NetBSD: patch-XSA-187-2,v 1.1 2016/09/08 15:41:01 bouyer Exp $ + +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> + +--- xen/arch/x86/mm/shadow/common.c.orig ++++ xen/arch/x86/mm/shadow/common.c +@@ -125,10 +125,19 @@ __initcall(shadow_audit_key_init); + /* x86 emulator support for the shadow code + */ + ++/* ++ * 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 *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; +@@ -145,14 +154,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); +@@ -254,9 +258,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); +@@ -284,9 +285,6 @@ hvm_emulate_cmpxchg(enum x86_segment seg + unsigned long addr, old[2], new[2]; + int rc; + +- if ( !is_x86_user_segment(seg) ) +- return X86EMUL_UNHANDLEABLE; +- + rc = hvm_translate_linear_addr( + seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); + if ( rc ) +--- xen/include/asm-x86/hvm/emulate.h.orig 2014-09-02 08:22:57.000000000 +0200 ++++ xen/include/asm-x86/hvm/emulate.h 2016-09-08 15:57:32.000000000 +0200 +@@ -13,6 +13,7 @@ + #define __ASM_X86_HVM_EMULATE_H__ + + #include <xen/config.h> ++#include <xen/err.h> + #include <asm/x86_emulate.h> + + struct hvm_emulate_ctxt { +--- xen/arch/x86/hvm/emulate.c.orig 2014-09-02 08:22:57.000000000 +0200 ++++ xen/arch/x86/hvm/emulate.c 2016-09-08 16:01:31.000000000 +0200 +@@ -390,6 +390,8 @@ + *reps = min_t(unsigned long, *reps, 4096); + + 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) ) + { +@@ -777,6 +779,10 @@ + 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; + } +@@ -790,6 +796,9 @@ + 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); + +@@ -1130,10 +1139,17 @@ + } + } + ++/* ++ * 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]; |