From: Markus Armbruster <armbru@redhat.com>
To: Daniel Henrique Barboza <danielhb413@gmail.com>
Cc: Markus Armbruster <armbru@redhat.com>,
qemu-devel@nongnu.org, Peter Maydell <peter.maydell@linaro.org>,
qemu-arm@nongnu.org
Subject: Re: [PATCH v2 1/1] hw/arm: do not free machine->fdt in arm_load_dtb()
Date: Tue, 28 Mar 2023 11:53:32 +0200 [thread overview]
Message-ID: <87v8il19sz.fsf@pond.sub.org> (raw)
In-Reply-To: <49e58c51-fca4-6b6f-db4a-27e4cfefacd4@gmail.com> (Daniel Henrique Barboza's message of "Tue, 28 Mar 2023 06:34:28 -0300")
Daniel Henrique Barboza <danielhb413@gmail.com> writes:
> On 3/28/23 04:01, Markus Armbruster wrote:
>> Daniel Henrique Barboza <danielhb413@gmail.com> writes:
>>
>>> At this moment, arm_load_dtb() can free machine->fdt when
>>> binfo->dtb_filename is NULL. If there's no 'dtb_filename', 'fdt' will be
>>> retrieved by binfo->get_dtb(). If get_dtb() returns machine->fdt, as is
>>> the case of machvirt_dtb() from hw/arm/virt.c, fdt now has a pointer to
>>> machine->fdt. And, in that case, the existing g_free(fdt) at the end of
>>> arm_load_dtb() will make machine->fdt point to an invalid memory region.
>>>
>>> After the command 'dumpdtb' were introduced a couple of releases ago,
>>> running it with any ARM machine that uses arm_load_dtb() will crash
>>> QEMU.
>>>
>>> Let's enable all arm_load_dtb() callers to use dumpdtb properly. Instead
>>> of freeing 'fdt', assign it back to ms->fdt.
>>>
>>> Note that all current callers (sbsa-ref.c, virt.c, xlnx-versal-virt.c)
>>> are assigning ms->fdt before arm_load_dtb() is called, regardless of
>>> whether the user is inputting an external FDT via '-dtb'. To avoid
>>> leaking the board FDT if '-dtb' is used (since we're assigning ms->fdt
>>> in the end), free ms->fdt before load_device_tree().
>>>
>>> Cc: Peter Maydell <peter.maydell@linaro.org>
>>> Cc: qemu-arm@nongnu.org
>>> Fixes: bf353ad55590f ("qmp/hmp, device_tree.c: introduce dumpdtb")
>>> Reported-by: Markus Armbruster <armbru@redhat.com>i
>>> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
>>> ---
>>> hw/arm/boot.c | 10 +++++++++-
>>> 1 file changed, 9 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/hw/arm/boot.c b/hw/arm/boot.c
>>> index 50e5141116..de18c0a969 100644
>>> --- a/hw/arm/boot.c
>>> +++ b/hw/arm/boot.c
>>> @@ -549,6 +549,13 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
>>> goto fail;
>>> }
>>>
>>> + /*
>>> + * If we're here we won't be using the ms->fdt from the board.
>>> + * We'll assign a new ms->fdt at the end, so free it now to
>>> + * avoid leaking the board FDT.
>>> + */
>>> + g_free(ms->fdt);
>>> +
>>
>> "We will" is not true: we will not if we goto fail. Leaves ms->fdt
>> dangling, doesn't it?
>
> We can postpone this g_free() to execute after "if (!fdt) {}" to be sure that we're
> not freeing ms->fdt right before 'goto fail'.
Yes, but what about all the goto fail further down?
>>> fdt = load_device_tree(filename, &size);
>>> if (!fdt) {
>>> fprintf(stderr, "Couldn't open dtb file %s\n", filename);
>> g_free(filename);
>> goto fail;
>> }
>> g_free(filename);
>> } else {
>> fdt = binfo->get_dtb(binfo, &size);
>> if (!fdt) {
>> fprintf(stderr, "Board was unable to create a dtb blob\n");
>> goto fail;
>> }
>>
>> If we succeed, we'll assign @fdt to ms->fdt (next hunk). Won't this
>> leak old ms->fdt?
>
>
> For all callers binfo->get_dtb() is returning ms->fdt, i.e. this line:
>
> fdt = binfo->get_dtb(binfo, &size);
>
> Is equal to this:
>
> fdt = ms->fdt;
>
> And this is why we can't unconditionally do a g_free(ms->fdt).
Uff. Not exactly obvious.
> I believe we can improve the ARM boot code to not create ms->fdt at init(),
> leaving it unassigned, and make get_dtb() return the machine FDT on a common
> "void *" pointer. That would spare us from having go g_free(ms->fdt) to avoid
> leaks and we would assign ms->fdt at the end of arm_load_dtb() normally. I made
> a quick attempt at that but the ARM init() code is a little tricker than I've
> anticipated. I might have a crack at it later.
Do we want a quick interim fix for 8.0?
Have a careful look at the untested patch below.
> Thanks,
>
> Daniel
>
>
>>
>> }
>>
>>> @@ -689,7 +696,8 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
>>> qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
>>> rom_ptr_for_as(as, addr, size));
>>>
>>> - g_free(fdt);
>>> + /* Set ms->fdt for 'dumpdtb' QMP/HMP command */
>>> + ms->fdt = fdt;
>>>
>>> return size;
>>
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 50e5141116..54f6a3e0b3 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -689,7 +689,10 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo,
qemu_register_reset_nosnapshotload(qemu_fdt_randomize_seeds,
rom_ptr_for_as(as, addr, size));
- g_free(fdt);
+ if (fdt != ms->fdt) {
+ g_free(ms->fdt);
+ ms->fdt = fdt;
+ }
return size;
next prev parent reply other threads:[~2023-03-28 9:53 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-03-23 20:44 [PATCH v2 0/1] fix dumpdtb crash with ARM machines Daniel Henrique Barboza
2023-03-23 20:44 ` [PATCH v2 1/1] hw/arm: do not free machine->fdt in arm_load_dtb() Daniel Henrique Barboza
2023-03-28 7:01 ` Markus Armbruster
2023-03-28 9:34 ` Daniel Henrique Barboza
2023-03-28 9:53 ` Markus Armbruster [this message]
2023-03-28 12:54 ` Daniel Henrique Barboza
2023-03-28 16:58 ` Markus Armbruster
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87v8il19sz.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=danielhb413@gmail.com \
--cc=peter.maydell@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.