From: Jan Beulich Date: Thu, 28 May 2020 10:00:24 +0000 (+0200) Subject: x86: relax LDT check in arch_set_info_guest() X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=cb8a478e1d246c1273e457d9c48d4609416c82e5;p=people%2Fsstabellini%2Fxen-unstable.git%2F.git x86: relax LDT check in arch_set_info_guest() It is wrong for us to check the base address when there's no LDT in the first place. Once we don't do this check anymore we can also set the base address to a non-canonical value when the LDT is empty. Signed-off-by: Jan Beulich Reviewed-by: Roger Pau Monné Acked-by: Andrew Cooper --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 6327ba0790..fee6c3931a 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -967,8 +967,10 @@ int arch_set_info_guest( if ( !compat && !(flags & VGCF_in_kernel) && !c.nat->ctrlreg[1] ) return -EINVAL; - v->arch.pv.ldt_base = c(ldt_base); v->arch.pv.ldt_ents = c(ldt_ents); + v->arch.pv.ldt_base = v->arch.pv.ldt_ents + ? c(ldt_base) + : (unsigned long)ZERO_BLOCK_PTR; } else { @@ -997,8 +999,9 @@ int arch_set_info_guest( for ( i = 0; !fail && i < nr_gdt_frames; ++i ) fail = v->arch.pv.gdt_frames[i] != c(gdt_frames[i]); - fail |= v->arch.pv.ldt_base != c(ldt_base); fail |= v->arch.pv.ldt_ents != c(ldt_ents); + if ( v->arch.pv.ldt_ents ) + fail |= v->arch.pv.ldt_base != c(ldt_base); if ( fail ) return -EOPNOTSUPP; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 8c55db2f69..6f2c69788d 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1583,7 +1583,7 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) } else { - c(ldt_base = v->arch.pv.ldt_base); + c(ldt_base = v->arch.pv.ldt_ents ? v->arch.pv.ldt_base : 0); c(ldt_ents = v->arch.pv.ldt_ents); for ( i = 0; i < ARRAY_SIZE(v->arch.pv.gdt_frames); ++i ) c(gdt_frames[i] = v->arch.pv.gdt_frames[i]); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index e42044eb74..54980b4eb1 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -3669,14 +3669,15 @@ long do_mmuext_op( case MMUEXT_SET_LDT: { unsigned int ents = op.arg2.nr_ents; - unsigned long ptr = ents ? op.arg1.linear_addr : 0; + unsigned long ptr = ents ? op.arg1.linear_addr + : (unsigned long)ZERO_BLOCK_PTR; if ( unlikely(currd != pg_owner) ) rc = -EPERM; else if ( paging_mode_external(currd) ) rc = -EINVAL; - else if ( ((ptr & (PAGE_SIZE - 1)) != 0) || !__addr_ok(ptr) || - (ents > 8192) ) + else if ( (ents > 8192) || + (ents && ((ptr & (PAGE_SIZE - 1)) || !__addr_ok(ptr))) ) { gdprintk(XENLOG_WARNING, "Bad args to SET_LDT: ptr=%lx, ents=%x\n", ptr, ents);