[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 2/3] x86/hvm: introduce functions for HVMOP_get/set_param allowance checks
On 24/04/15 17:21, Paul Durrant wrote: > Some parameters can only (validly) be set once. Some cannot be set > by a guest for its own domain. Consolidate these checks, along with > the XSM check, in a new hvm_allow_set_param() function for clarity. > > Also, introduce hvm_allow_get_param() for similar reasons. > > Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> > Cc: Keir Fraser <keir@xxxxxxx> > Cc: Jan Beulich <jbeulich@xxxxxxxx> > Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> > --- > xen/arch/x86/hvm/hvm.c | 141 > +++++++++++++++++++++++++++--------------------- > 1 file changed, 79 insertions(+), 62 deletions(-) > > diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c > index 87c47b1..23c604d 100644 > --- a/xen/arch/x86/hvm/hvm.c > +++ b/xen/arch/x86/hvm/hvm.c > @@ -5640,6 +5640,57 @@ static int hvmop_set_evtchn_upcall_vector( > return 0; > } > > +static int hvm_allow_set_param(struct domain *d, > + struct xen_hvm_param *a) const > +{ > + uint64_t value = d->arch.hvm_domain.params[a->index]; > + int rc = 0; No need for the 0 initialiser (and I know Coverity will complain about it). > + > + rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_set_param); > + if ( rc ) > + return rc; > + > + /* The following parameters cannot be set by the guest */ > + switch (a->index) style > + { > + case HVM_PARAM_VIRIDIAN: > + case HVM_PARAM_IDENT_PT: > + case HVM_PARAM_DM_DOMAIN: > + case HVM_PARAM_ACPI_S_STATE: > + case HVM_PARAM_MEMORY_EVENT_CR0: > + case HVM_PARAM_MEMORY_EVENT_CR3: > + case HVM_PARAM_MEMORY_EVENT_CR4: > + case HVM_PARAM_MEMORY_EVENT_INT3: > + case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP: > + case HVM_PARAM_MEMORY_EVENT_MSR: > + case HVM_PARAM_IOREQ_SERVER_PFN: > + case HVM_PARAM_NR_IOREQ_SERVER_PAGES: > + if ( d == current->domain ) > + rc = -EPERM; > + break; > + default: > + break; Please can we turn the guest-settable list into a whitelist rather than a blacklist. We have had several XSAs in the past where a guest has been able to modify a value it shouldn't have because new params were default writable by everyone. > + } > + > + if ( rc ) > + return rc; > + > + /* The following parameters can only be changed once */ > + switch (a->index) > + { > + case HVM_PARAM_VIRIDIAN: > + case HVM_PARAM_IOREQ_SERVER_PFN: > + case HVM_PARAM_NR_IOREQ_SERVER_PAGES: > + if (value != 0 && a->value != value) > + rc = -EEXIST; > + break; > + default: > + break; > + } > + > + return rc; > +} > + > static int hvmop_set_param( > XEN_GUEST_HANDLE_PARAM(xen_hvm_param_t) arg) > { > @@ -5666,7 +5717,7 @@ static int hvmop_set_param( > && (a.index != HVM_PARAM_CALLBACK_IRQ) ) > goto out; > > - rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_set_param); > + rc = hvm_allow_set_param(d, &a); > if ( rc ) > goto out; > > @@ -5681,31 +5732,11 @@ static int hvmop_set_param( > rc = -EINVAL; > break; > case HVM_PARAM_VIRIDIAN: > - /* This should only ever be set once by the tools and read by the > guest. */ > - rc = -EPERM; > - if ( d == current->domain ) > - break; > - > - if ( a.value != d->arch.hvm_domain.params[a.index] ) > - { > - rc = -EEXIST; > - if ( d->arch.hvm_domain.params[a.index] != 0 ) > - break; > - > + if ( (a.value & ~HVMPV_feature_mask) || > + !(a.value & HVMPV_base_freq) ) > rc = -EINVAL; > - if ( (a.value & ~HVMPV_feature_mask) || > - !(a.value & HVMPV_base_freq) ) > - break; > - } > - > - rc = 0; > break; > case HVM_PARAM_IDENT_PT: > - /* Not reflexive, as we must domain_pause(). */ > - rc = -EPERM; > - if ( d == current->domain ) > - break; > - > rc = -EINVAL; > if ( d->arch.hvm_domain.params[a.index] != 0 ) > break; > @@ -5733,22 +5764,12 @@ static int hvmop_set_param( > domctl_lock_release(); > break; > case HVM_PARAM_DM_DOMAIN: > - /* Not reflexive, as we may need to domain_pause(). */ > - rc = -EPERM; > - if ( d == current->domain ) > - break; > - > if ( a.value == DOMID_SELF ) > a.value = current->domain->domain_id; > > rc = hvm_set_dm_domain(d, a.value); > break; > case HVM_PARAM_ACPI_S_STATE: > - /* Not reflexive, as we must domain_pause(). */ > - rc = -EPERM; > - if ( current->domain == d ) > - break; > - > rc = 0; > if ( a.value == 3 ) > hvm_s3_suspend(d); > @@ -5761,20 +5782,9 @@ static int hvmop_set_param( > case HVM_PARAM_ACPI_IOPORTS_LOCATION: > rc = pmtimer_change_ioport(d, a.value); > break; > - case HVM_PARAM_MEMORY_EVENT_CR0: > - case HVM_PARAM_MEMORY_EVENT_CR3: > - case HVM_PARAM_MEMORY_EVENT_CR4: > - if ( d == current->domain ) > - rc = -EPERM; > - break; > case HVM_PARAM_MEMORY_EVENT_INT3: > case HVM_PARAM_MEMORY_EVENT_SINGLE_STEP: > case HVM_PARAM_MEMORY_EVENT_MSR: > - if ( d == current->domain ) > - { > - rc = -EPERM; > - break; > - } > if ( a.value & HVMPME_onchangeonly ) > rc = -EINVAL; > break; > @@ -5807,22 +5817,12 @@ static int hvmop_set_param( > rc = -EINVAL; > break; > case HVM_PARAM_IOREQ_SERVER_PFN: > - if ( d == current->domain ) > - { > - rc = -EPERM; > - break; > - } > d->arch.hvm_domain.ioreq_gmfn.base = a.value; > break; > case HVM_PARAM_NR_IOREQ_SERVER_PAGES: > { > unsigned int i; > > - if ( d == current->domain ) > - { > - rc = -EPERM; > - break; > - } > if ( a.value == 0 || > a.value > sizeof(d->arch.hvm_domain.ioreq_gmfn.mask) * 8 ) > { > @@ -5866,6 +5866,30 @@ static int hvmop_set_param( > return rc; > } > > +static int hvm_allow_get_param(struct domain *d, > + struct xen_hvm_param *a) > +{ > + int rc = 0; > + > + rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_get_param); > + if ( rc ) > + return rc; > + > + /* The following parameters cannot be read by the guest */ > + switch (a->index) > + { > + case HVM_PARAM_IOREQ_SERVER_PFN: > + case HVM_PARAM_NR_IOREQ_SERVER_PAGES: > + if ( d == current->domain ) > + rc = -EPERM; > + break; > + default: > + break; Again, this would be safer as a whitelist. ~Andrew > + } > + > + return rc; > +} > + > static int hvmop_get_param( > XEN_GUEST_HANDLE_PARAM(xen_hvm_param_t) arg) > { > @@ -5891,7 +5915,7 @@ static int hvmop_get_param( > && (a.index != HVM_PARAM_CALLBACK_IRQ) ) > goto out; > > - rc = xsm_hvm_param(XSM_TARGET, d, HVMOP_get_param); > + rc = hvm_allow_get_param(d, &a); > if ( rc ) > goto out; > > @@ -5900,13 +5924,6 @@ static int hvmop_get_param( > case HVM_PARAM_ACPI_S_STATE: > a.value = d->arch.hvm_domain.is_s3_suspended ? 3 : 0; > break; > - case HVM_PARAM_IOREQ_SERVER_PFN: > - case HVM_PARAM_NR_IOREQ_SERVER_PAGES: > - if ( d == current->domain ) > - { > - rc = -EPERM; > - goto out; > - } > case HVM_PARAM_IOREQ_PFN: > case HVM_PARAM_BUFIOREQ_PFN: > case HVM_PARAM_BUFIOREQ_EVTCHN: { _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |