diff options
Diffstat (limited to 'system/xen/xsa/xsa298.patch')
-rw-r--r-- | system/xen/xsa/xsa298.patch | 89 |
1 files changed, 0 insertions, 89 deletions
diff --git a/system/xen/xsa/xsa298.patch b/system/xen/xsa/xsa298.patch deleted file mode 100644 index aa39042be5..0000000000 --- a/system/xen/xsa/xsa298.patch +++ /dev/null @@ -1,89 +0,0 @@ -From: Jan Beulich <jbeulich@suse.com> -Subject: x86/PV: check GDT/LDT limits during emulation - -Accesses beyond the LDT limit originating from emulation would trigger -the ASSERT() in pv_map_ldt_shadow_page(). On production builds such -accesses would cause an attempt to promote the touched page (offset from -the present LDT base address) to a segment descriptor one. If this -happens to succeed, guest user mode would be able to elevate its -privileges to that of the guest kernel. This is particularly easy when -there's no LDT at all, in which case the LDT base stored internally to -Xen is simply zero. - -Also adjust the ASSERT() that was triggering: It was off by one to -begin with, and for production builds we also better use -ASSERT_UNREACHABLE() instead with suitable recovery code afterwards. - -This is XSA-298. - -Reported-by: Andrew Cooper <andrew.cooper3@citrix.com> -Signed-off-by: Jan Beulich <jbeulich@suse.com> -Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> ---- -v2: Correct 64-bit-only limit check (by folding into the common one). - ---- a/xen/arch/x86/pv/emul-gate-op.c -+++ b/xen/arch/x86/pv/emul-gate-op.c -@@ -51,7 +51,13 @@ static int read_gate_descriptor(unsigned - const seg_desc_t *pdesc = gdt_ldt_desc_ptr(gate_sel); - - if ( (gate_sel < 4) || -- ((gate_sel >= FIRST_RESERVED_GDT_BYTE) && !(gate_sel & 4)) || -+ /* -+ * We're interested in call gates only, which occupy a single -+ * seg_desc_t for 32-bit and a consecutive pair of them for 64-bit. -+ */ -+ ((gate_sel >> 3) + !is_pv_32bit_vcpu(v) >= -+ (gate_sel & 4 ? v->arch.pv.ldt_ents -+ : v->arch.pv.gdt_ents)) || - __get_user(desc, pdesc) ) - return 0; - -@@ -70,7 +76,7 @@ static int read_gate_descriptor(unsigned - if ( !is_pv_32bit_vcpu(v) ) - { - if ( (*ar & 0x1f00) != 0x0c00 || -- (gate_sel >= FIRST_RESERVED_GDT_BYTE - 8 && !(gate_sel & 4)) || -+ /* Limit check done above already. */ - __get_user(desc, pdesc + 1) || - (desc.b & 0x1f00) ) - return 0; ---- a/xen/arch/x86/pv/emulate.c -+++ b/xen/arch/x86/pv/emulate.c -@@ -31,7 +31,14 @@ int pv_emul_read_descriptor(unsigned int - { - seg_desc_t desc; - -- if ( sel < 4) -+ if ( sel < 4 || -+ /* -+ * Don't apply the GDT limit here, as the selector may be a Xen -+ * provided one. __get_user() will fail (without taking further -+ * action) for ones falling in the gap between guest populated -+ * and Xen ones. -+ */ -+ ((sel & 4) && (sel >> 3) >= v->arch.pv.ldt_ents) ) - desc.b = desc.a = 0; - else if ( __get_user(desc, gdt_ldt_desc_ptr(sel)) ) - return 0; ---- a/xen/arch/x86/pv/mm.c -+++ b/xen/arch/x86/pv/mm.c -@@ -92,12 +92,16 @@ bool pv_map_ldt_shadow_page(unsigned int - BUG_ON(unlikely(in_irq())); - - /* -- * Hardware limit checking should guarantee this property. NB. This is -+ * Prior limit checking should guarantee this property. NB. This is - * safe as updates to the LDT can only be made by MMUEXT_SET_LDT to the - * current vcpu, and vcpu_reset() will block until this vcpu has been - * descheduled before continuing. - */ -- ASSERT((offset >> 3) <= curr->arch.pv.ldt_ents); -+ if ( unlikely((offset >> 3) >= curr->arch.pv.ldt_ents) ) -+ { -+ ASSERT_UNREACHABLE(); -+ return false; -+ } - - if ( is_pv_32bit_domain(currd) ) - linear = (uint32_t)linear; |