[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH SpectreV1+L1TF v5 1/9] xen/evtchn: block speculative out-of-bound accesses



>>> On 29.01.19 at 15:43, <nmanthey@xxxxxxxxx> wrote:
> --- a/xen/common/event_channel.c
> +++ b/xen/common/event_channel.c
> @@ -365,11 +365,16 @@ int evtchn_bind_virq(evtchn_bind_virq_t *bind, 
> evtchn_port_t port)
>      if ( (virq < 0) || (virq >= ARRAY_SIZE(v->virq_to_evtchn)) )
>          return -EINVAL;
>  
> +   /*
> +    * Make sure the guest controlled value virq is bounded even during
> +    * speculative execution.
> +    */
> +    virq = array_index_nospec(virq, ARRAY_SIZE(v->virq_to_evtchn));
> +
>      if ( virq_is_global(virq) && (vcpu != 0) )
>          return -EINVAL;
>  
> -    if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
> -         ((v = d->vcpu[vcpu]) == NULL) )
> +    if ( (vcpu < 0) || ((v = domain_vcpu(d, vcpu)) == NULL) )
>          return -ENOENT;

Is there a reason for the less-than-zero check to survive?

> @@ -418,8 +423,7 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
>      int            port, vcpu = bind->vcpu;
>      long           rc = 0;
>  
> -    if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
> -         (d->vcpu[vcpu] == NULL) )
> +    if ( (vcpu < 0) || domain_vcpu(d, vcpu) == NULL )
>          return -ENOENT;

I'm not sure about this one: We're not after the struct vcpu pointer
here. Right now subsequent code looks fine, but what if the actual
"vcpu" local variable was used again in a risky way further down? I
think here and elsewhere it would be best to eliminate that local
variable, and use v->vcpu_id only for subsequent consumers (or
alternatively latch the local variable's value only _after_ the call to
domain_vcpu(), which might be better especially in cases like).

> @@ -969,8 +980,8 @@ long evtchn_bind_vcpu(unsigned int port, unsigned int 
> vcpu_id)
>          unlink_pirq_port(chn, d->vcpu[chn->notify_vcpu_id]);
>          chn->notify_vcpu_id = vcpu_id;
>          pirq_set_affinity(d, chn->u.pirq.irq,
> -                          cpumask_of(d->vcpu[vcpu_id]->processor));
> -        link_pirq_port(port, chn, d->vcpu[vcpu_id]);
> +                          cpumask_of(domain_vcpu(d, vcpu_id)->processor));
> +        link_pirq_port(port, chn, domain_vcpu(d, vcpu_id));

... this one, where you then wouldn't need to alter code other than
that actually checking the vCPU ID.

> @@ -516,14 +517,22 @@ int evtchn_fifo_init_control(struct evtchn_init_control 
> *init_control)
>      gfn     = init_control->control_gfn;
>      offset  = init_control->offset;
>  
> -    if ( vcpu_id >= d->max_vcpus || !d->vcpu[vcpu_id] )
> +    if ( !domain_vcpu(d, vcpu_id) )
>          return -ENOENT;
> -    v = d->vcpu[vcpu_id];
> +
> +    v = domain_vcpu(d, vcpu_id);

Please don't call the function twice.

Jan



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.