From: Jan Beulich Subject: x86/domain: locking for ioport_caps accesses In order to be able to pull at least the XEN_DOMCTL_ioport_mapping handling out of the domctl-locked region, the new separate (per-domain) lock is used to synchronize in particular with XEN_DOMCTL_ioport_permission. Locking is added only as far as domctl-s are affected. Uses presently outside of the domctl lock may want dealing with subsequently (perhaps limited to non-__init code). This is part of XSA-492. Signed-off-by: Jan Beulich Reviewed-by: Roger Pau Monné --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -226,6 +226,8 @@ long arch_do_domctl( unsigned int np = domctl->u.ioport_permission.nr_ports; int allow = domctl->u.ioport_permission.allow_access; + iocaps_double_lock(d, true); + if ( (fp + np) <= fp || (fp + np) > MAX_IOPORTS ) ret = -EINVAL; else if ( !ioports_access_permitted(currd, fp, fp + np - 1) || @@ -235,6 +237,8 @@ long arch_do_domctl( ret = ioports_permit_access(d, fp, fp + np - 1); else ret = ioports_deny_access(d, fp, fp + np - 1); + + iocaps_double_unlock(d, true); break; } @@ -605,16 +609,13 @@ long arch_do_domctl( break; } - ret = -EPERM; - if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) ) - break; - - ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add); - if ( ret ) - break; - hvm = &d->arch.hvm; - if ( add ) + iocaps_double_lock(d, true); + + if ( !ioports_access_permitted(currd, fmp, fmp + np - 1) || + (ret = xsm_ioport_mapping(XSM_HOOK, d, fmp, fmp + np - 1, add)) ) + ret = ret ?: -EPERM; + else if ( add ) { printk(XENLOG_G_INFO "ioport_map:add: dom%d gport=%x mport=%x nr=%x\n", @@ -675,6 +677,8 @@ long arch_do_domctl( "ioport_map: error %ld denying dom%d access to [%x,%x]\n", ret, d->domain_id, fmp, fmp + np - 1); } + + iocaps_double_unlock(d, true); break; } --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -2086,9 +2086,13 @@ void __hwdom_init setup_io_bitmap(struct if ( is_hvm_domain(d) ) { bitmap_fill(d->arch.hvm.io_bitmap, 0x10000); + + read_lock(&d->caps_lock); rc = rangeset_report_ranges(d->arch.ioport_caps, 0, 0x10000, io_bitmap_cb, d); BUG_ON(rc); + read_unlock(&d->caps_lock); + /* * NB: we need to trap accesses to 0xcf8 in order to intercept * 4 byte accesses, that need to be handled by Xen in order to