@@ -1081,7 +1081,6 @@ int arch_set_info_guest(
if ( !is_canonical_address(c.nat->user_regs.rip) ||
!is_canonical_address(c.nat->user_regs.rsp) ||
!is_canonical_address(c.nat->kernel_sp) ||
- (c.nat->ldt_ents && !is_canonical_address(c.nat->ldt_base)) ||
!is_canonical_address(c.nat->fs_base) ||
!is_canonical_address(c.nat->gs_base_kernel) ||
!is_canonical_address(c.nat->gs_base_user) ||
@@ -1100,9 +1099,6 @@ int arch_set_info_guest(
return -EINVAL;
fixup_guest_code_selector(d, c.nat->trap_ctxt[i].cs);
}
-
- if ( !__addr_ok(c.nat->ldt_base) )
- return -EINVAL;
}
#ifdef CONFIG_COMPAT
else
@@ -1119,8 +1115,7 @@ int arch_set_info_guest(
#endif
/* LDT safety checks. */
- if ( ((c(ldt_base) & (PAGE_SIZE - 1)) != 0) ||
- (c(ldt_ents) > 8192) )
+ if ( !pv_is_valid_ldt(c(ldt_base), c(ldt_ents)) )
return -EINVAL;
v->arch.pv.vgc_flags = flags;
@@ -46,4 +46,14 @@ static inline bool pv_destroy_ldt(struct
#endif
+static inline bool pv_is_valid_ldt(unsigned long base, unsigned int ents)
+{
+ if ( !ents )
+ return true;
+
+ return !(base & (PAGE_SIZE - 1)) && ents <= 8192 &&
+ is_canonical_address(base) &&
+ is_canonical_address(base + ents * 8 - 1);
+}
+
#endif /* __X86_PV_MM_H__ */
@@ -3800,8 +3800,7 @@ long do_mmuext_op(
rc = -EPERM;
else if ( paging_mode_external(currd) )
rc = -EINVAL;
- else if ( (ents > 8192) ||
- (ents && ((ptr & (PAGE_SIZE - 1)) || !__addr_ok(ptr))) )
+ else if ( !pv_is_valid_ldt(ptr, ents) )
{
gdprintk(XENLOG_WARNING,
"Bad args to SET_LDT: ptr=%lx, ents=%x\n", ptr, ents);
Consolidate all hypercall time checking into a single helper function, checking only static properties. The dynamic properties are already taken care of by the __addr_ok() check in guest_get_eff_kern_l1e(), used by pv_map_ldt_shadow_page(), in a formally more "precise" manner (accounting for the offset into the table). Signed-off-by: Jan Beulich <jbeulich@suse.com>