On 31/03/2021 15:03, Jan Beulich wrote:
> On 31.03.2021 15:31, Andrew Cooper wrote:
>> vlapic_init()'s caller calls vlapic_destroy() on error.  Therefore, the error
>> path from __map_domain_page_global() failing would doubly free
>> vlapic->regs_page.
> I'm having difficulty seeing this. What I find at present is
>
>     rc = vlapic_init(v);
>     if ( rc != 0 ) /* teardown: vlapic_destroy */
>         goto fail2;
>
> and then
>
>  fail3:
>     vlapic_destroy(v);
>  fail2:
>
> Am I missing some important aspect?

No - I'm blind.  (although I do blame the code comment for being
actively misleading.)

I retract the patch at this point.  It needs to be part of a bigger
series making changes like this consistently across the callers.

>> Rework vlapic_destroy() to be properly idempotent, introducing the necessary
>> UNMAP_DOMAIN_PAGE_GLOBAL() and FREE_DOMHEAP_PAGE() wrappers.
>>
>> Rearrange vlapic_init() to group all trivial initialisation, and leave all
>> cleanup to the caller, in line with our longer term plans.
> Cleanup functions becoming idempotent is what I understand is the
> longer term plan. I didn't think this necessarily included leaving
> cleanup after failure in a function to it caller(s).

That's literally the point of the exercise.

>  At least in the
> general case I think it would be quite a bit better if functions
> cleaned up after themselves - perhaps (using the example here) by
> vlapic_init() calling vlapic_destroy() in such a case.

That pattern is the cause of code duplication (not a problem per say),
and many bugs (the problem needing solving) caused by the duplicated
logic not being equivalent.

We've got the start of the top-level pattern in progress, with
{domain,vcpu}_create() calling {d,v}_teardown() then {d,v}_destroy() for
errors.

This top-level pattern is also necessary so we can remove the need to
put partially constructed objects into full view of the system, and wait
for a subsequent hypercall to clean them up.  This series of bugs is
still active, and there are still a load of NULL pointer deferences
reachable from out-of-order toolstack hypercalls in failure cases.

We've also got some subsystems (vmtrace) moved into the new pattern, and
some minor parts of existing mess moved over too, but the end goal is to
have exactly one create() path and exactly one cleanup path, so its
impossible to introduce mismatched duplicate cleanup logic.

~Andrew


Reply via email to