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. 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...