|
[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
Hi Jan.
> On 22 Aug 2022, at 2:08 pm, Jan Beulich <jbeulich@xxxxxxxx> wrote:
>
> 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.
Ok. I will remove this and add that we need this patch to support static event
channel.
Something like:
“ When static event channel support will be added for dom0less domains
user can request to allocate the evtchn port numbers that are scattered
in nature."
>
>> Changes in v2:
>> - new patch in this version to fix the security issue
>
> I guess you mean "avoid", not "fix".
Ack.
>
>> @@ -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
Ack. I will fix this as suggested by you I next version.
Regards,
Rahul
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |