|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 1/7] xen/evtchn: Make sure all buckets below d->valid_evtchns are allocated
On 19.08.2022 12:02, Rahul Singh wrote:
> From: Julien Grall <jgrall@xxxxxxxxxx>
>
> Since commit 01280dc19cf3 "evtchn: simplify port_is_valid()", the event
> channels code assumes that all the buckets below d->valid_evtchns are
> always allocated.
>
> This assumption hold in most of the situation because a guest is not
> allowed to chose the port. Instead, it will be the first free from port
> 0.
>
> When using Guest Transparent Migration and LiveUpdate, we will only
> preserve ports that are currently in use. As a guest can open/close
> event channels, this means the ports may be sparse.
>
> The existing implementation of evtchn_allocate_port() is not able to
> deal with such situation and will end up to override bucket or/and leave
> some bucket unallocated. The latter will result to a droplet crash if
> the event channel belongs to an unallocated bucket.
>
> This can be solved by making sure that all the buckets below
> d->valid_evtchns are allocated. There should be no impact for most of
> the situation but LM/LU as only one bucket would be allocated. For
> LM/LU, we may end up to allocate multiple buckets if ports in use are
> sparse.
>
> A potential alternative is to check that the bucket is valid in
> is_port_valid(). This should still possible to do it without taking
> per-domain lock but will result a couple more of memory access.
>
> Signed-off-by: Julien Grall <jgrall@xxxxxxxxxx>
> Signed-off-by: Rahul Singh <rahul.singh@xxxxxxx>
While I'm mostly okay with the code, I think the description wants
changing / amending as long as the features talked about above aren't
anywhere near reaching upstream (afaict), to at least _also_ mention
the goal you have with this.
> Changes in v2:
> - new patch in this version to fix the security issue
I guess you mean "avoid", not "fix".
> @@ -207,30 +216,35 @@ int evtchn_allocate_port(struct domain *d,
> evtchn_port_t port)
> }
> else
> {
> - struct evtchn *chn;
> - struct evtchn **grp;
> -
> - if ( !group_from_port(d, port) )
> + do
> {
> - grp = xzalloc_array(struct evtchn *, BUCKETS_PER_GROUP);
> - if ( !grp )
> - return -ENOMEM;
> - group_from_port(d, port) = grp;
> - }
> + struct evtchn *chn;
> + struct evtchn **grp;
> + unsigned int alloc_port = read_atomic(&d->valid_evtchns);
>
> - chn = alloc_evtchn_bucket(d, port);
> - if ( !chn )
> - return -ENOMEM;
> - bucket_from_port(d, port) = chn;
> + if ( !group_from_port(d, alloc_port) )
> + {
> + grp = xzalloc_array(struct evtchn *, BUCKETS_PER_GROUP);
> + if ( !grp )
> + return -ENOMEM;
> + group_from_port(d, alloc_port) = grp;
> + }
>
> - /*
> - * d->valid_evtchns is used to check whether the bucket can be
> - * accessed without the per-domain lock. Therefore,
> - * d->valid_evtchns should be seen *after* the new bucket has
> - * been setup.
> - */
> - smp_wmb();
> - write_atomic(&d->valid_evtchns, d->valid_evtchns +
> EVTCHNS_PER_BUCKET);
> + chn = alloc_evtchn_bucket(d, alloc_port);
> + if ( !chn )
> + return -ENOMEM;
> + bucket_from_port(d, alloc_port) = chn;
> +
> + /*
> + * d->valid_evtchns is used to check whether the bucket can be
> + * accessed without the per-domain lock. Therefore,
> + * d->valid_evtchns should be seen *after* the new bucket has
> + * been setup.
> + */
> + smp_wmb();
> + write_atomic(&d->valid_evtchns,
> + d->valid_evtchns + EVTCHNS_PER_BUCKET);
> + } while ( port >= read_atomic(&d->valid_evtchns) );
This updating of d->valid_evtchns looks a little inconsistent to me,
wrt the uses of {read,write}_atomic(). To make obvious that there's
an implicit expectation that no 2nd invocation of this function
could race the updates, I'd recommend reading allocate_port ahead
of the loop and then never again. Here you'd then do
smp_wmb();
allocate_port += EVTCHNS_PER_BUCKET;
write_atomic(&d->valid_evtchns, allocate_port);
} while ( port >= allocate_port );
at the same time rendering the code (imo) a little more legible.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |