29.11.2019 18:23, Markus Armbruster wrote: > Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> writes: > >> 29.11.2019 17:11, Vladimir Sementsov-Ogievskiy wrote: >>> 29.11.2019 17:03, Markus Armbruster wrote: >>>> Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> writes: >>>> >>>>> fit_load_fdt forget to check that errp is not NULL and to zero it after >>>>> freeing. Fix it. >>>>> >>>>> Signed-off-by: Vladimir Sementsov-Ogievskiy <vsement...@virtuozzo.com> >>>>> Reviewed-by: Eric Blake <ebl...@redhat.com> >>>>> --- >>>>> hw/core/loader-fit.c | 5 ++++- >>>>> 1 file changed, 4 insertions(+), 1 deletion(-) >>>>> >>>>> diff --git a/hw/core/loader-fit.c b/hw/core/loader-fit.c >>>>> index 953b16bc82..3ee9fb2f2e 100644 >>>>> --- a/hw/core/loader-fit.c >>>>> +++ b/hw/core/loader-fit.c >>>>> @@ -200,7 +200,10 @@ static int fit_load_fdt(const struct fit_loader >>>>> *ldr, const void *itb, >>>>> err = fit_image_addr(itb, img_off, "load", &load_addr, errp); >>>>> if (err == -ENOENT) { >>>>> load_addr = ROUND_UP(kernel_end, 64 * KiB) + (10 * MiB); >>>>> - error_free(*errp); >>>>> + if (errp) { >>>>> + error_free(*errp); >>>>> + *errp = NULL; >>>>> + } >>>>> } else if (err) { >>>>> error_prepend(errp, "unable to read FDT load address from FIT: >>>>> "); >>>>> ret = err; >>>> >>>> This fixes latent bugs when fit_image_addr() fails with ENOENT: >>>> >>>> * If a caller passes a null @errp, we crash dereferencing it >>>> >>>> * Else, we pass a dangling Error * to the caller, and return success. >>>> If a caller dereferences the Error * regardless, we have a >>>> use-after-free. >>>> >>>> Not fixed: >>>> >>>> * If a caller passes &error_abort or &error_fatal, we die instead of >>>> taking the recovery path. >>> >>> No, if it is error_abort or error_fatal, we will not reach this point, the >>> execution >>> finished before, when error was set. >> >> Ah, that is what you mention.. Hmm. Is it bad? At least crashing on >> error_abort without any recovery should not be bad.. > > Latent bugs aren't bad, but they could possibly become bad :) > > When you pass &err to fit_load_fdt(), where @err is a local variable, > the ENOENT case is not actually an error; fit_load_fdt() recovers fine > and succeeds. > > When you pass &error_fatal or &error_abort, it should likewise not be an > error.
Ah, yes, understand now. Interesting, that auto-propageted errp will not catch this. It will only help with error_fatal, but not with error_abort.. So, in this case we should wrap error_abort too. And it in every function that uses error_free. And this means, that in this case we can't make error_abort crash at point where actual error occures. That is very sad. > > General rule: when you want to handle some (or all) of a function's > errors yourself, you must not pass your own @errp argument. Instead, > pass &err and propagate the errors you don't handle yourself with > error_propagate(errp, err). > >>>> We need to use a local_err here. >>>> >>>> I'll search for the pattern, and post fix(es). > > Found several bugs already... > -- Best regards, Vladimir