qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Shannon Zhao <zhaoshenglong@huawei.com>
To: Auger Eric <eric.auger@redhat.com>,
	Peter Maydell <peter.maydell@linaro.org>
Cc: qemu-arm <qemu-arm@nongnu.org>,
	QEMU Developers <qemu-devel@nongnu.org>,
	Shannon Zhao <shannon.zhaosl@gmail.com>
Subject: Re: [Qemu-devel] [PATCH v2] ARM: ACPI: Fix use-after-free due to memory realloc
Date: Wed, 30 May 2018 09:14:52 +0800	[thread overview]
Message-ID: <5B0DFB0C.3000002@huawei.com> (raw)
In-Reply-To: <383b0c0b-4406-869c-5493-df2f48896113@redhat.com>



On 2018/5/30 3:53, Auger Eric wrote:
> Hi Shannon,
> 
> On 05/29/2018 04:09 PM, Shannon Zhao wrote:
>>
>>
>>> 在 2018年5月29日,21:53,Peter Maydell <peter.maydell@linaro.org> 写道:
>>>
>>>> On 29 May 2018 at 04:08, Shannon Zhao <zhaoshenglong@huawei.com> wrote:
>>>> acpi_data_push uses g_array_set_size to resize the memory size. If there
>>>> is no enough contiguous memory, the address will be changed. So previous
>>>> pointer could not be used any more. It must update the pointer and use
>>>> the new one.
>>>>
>>>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>> Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
>>>> ---
>>>> V2: add comments for iort_node_offset and reviewed tags
>>>> ---
>>>> hw/arm/virt-acpi-build.c | 19 +++++++++++++++----
>>>> 1 file changed, 15 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
>>>> index 92ceee9..6209138 100644
>>>> --- a/hw/arm/virt-acpi-build.c
>>>> +++ b/hw/arm/virt-acpi-build.c
>>>> @@ -400,7 +400,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>     AcpiIortItsGroup *its;
>>>>     AcpiIortTable *iort;
>>>>     AcpiIortSmmu3 *smmu;
>>>> -    size_t node_size, iort_length, smmu_offset = 0;
>>>> +    size_t node_size, iort_node_offset, iort_length, smmu_offset = 0;
>>>>     AcpiIortRC *rc;
>>>>
>>>>     iort = acpi_data_push(table_data, sizeof(*iort));
>>>> @@ -415,6 +415,12 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>     iort->node_count = cpu_to_le32(nb_nodes);
>>>>     iort->node_offset = cpu_to_le32(sizeof(*iort));
>>>>
>>>> +    /*
>>>> +     * Use a copy in case table_data->data moves duringa acpi_data_push
>>>> +     * operations.
>>>> +     */
>>>> +    iort_node_offset = sizeof(*iort);
>>>> +
>>>>     /* ITS group node */
>>>>     node_size =  sizeof(*its) + sizeof(uint32_t);
>>>>     iort_length += node_size;
>>>> @@ -429,7 +435,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>         int irq =  vms->irqmap[VIRT_SMMU];
>>>>
>>>>         /* SMMUv3 node */
>>>> -        smmu_offset = iort->node_offset + node_size;
>>>> +        smmu_offset = iort_node_offset + node_size;
>>>
>>> In the old code, we used iort->node_offset directly as a CPU
>>> endianness order bitmap, which is initialized above using
>>>    iort->node_offset = cpu_to_le32(sizeof(*iort));
>>> In this version, we use iort_node_offset, which is
>>> initialized using
>>>    iort_node_offset = sizeof(*iort);
>>>
>>> So we've lost an endianness conversion on big-endian systems.
>>> Which is correct, the old code or the new?
>> I think it’s the new one. I found this bug later and wanted to send another patch to fix it. But to address Philippe’s comment I folder them together.
> Shouldn't we have
> iort_node_offset = iort->node_offset;
> iort->node_offset = cpu_to_le32(iort_node_offset);
> instead?
> 
Hi Eric,
Have you read this patch and code carefully?

I think you mean
iort_node_offset = sizeof(*iort);
iort->node_offset = cpu_to_le32(iort_node_offset);

Right? If so it's almost same with what I write. I just use sizeof twice.

iort->node_offset = cpu_to_le32(sizeof(*iort));
iort_node_offset = sizeof(*iort);

> Otherwise subsequent computations are done with the node_offset already
> converted to le32 whereas the cpu mode may be "be"?
> 
What I did here is to avoid the case you mentioned.
The iort_node_offset is host order, right? And I use iort_node_offset
instead of iort->node_offset for subsequent computations not the le32
one. So smmu_offset = iort_node_offset + node_size; will get the right
value as well as below ones.

Thanks,

> Shouldn't conversions to le32 being done at the last stage when
> populating the structs?
> 
> May be worth splitting this into 2 patches then or at least mentioning
> this other fix in the commit message?
> 
> Thanks
> 
> Eric
> 
>>
>>>
>>>>         node_size = sizeof(*smmu) + sizeof(*idmap);
>>>>         iort_length += node_size;
>>>>         smmu = acpi_data_push(table_data, node_size);
>>>> @@ -450,7 +456,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>         idmap->id_count = cpu_to_le32(0xFFFF);
>>>>         idmap->output_base = 0;
>>>>         /* output IORT node is the ITS group node (the first node) */
>>>> -        idmap->output_reference = cpu_to_le32(iort->node_offset);
>>>> +        idmap->output_reference = cpu_to_le32(iort_node_offset);
>>>
>>> Here we're doing an endianness conversion on iort_node_offset.
>>>
>>> Overall something is weird here, even in the previous version:
>>> if we wrote iort->node_offset with cpu_to_le32(), that implies
>>> that it's little-endian; so why are we reading it with cpu_to_le32()
>>> here rather than le32_to_cpu() ?
>>> Both cpu_to_le32() and le32_to_cpu() are the same operation,
>>> mathematically, but we should use the version which indicates
>>> our intent, ie which of source and destination is the always-LE
>>> data, and which is the host-order data.
>>>
>>>>     }
>>>>
>>>>     /* Root Complex Node */
>>>> @@ -479,9 +485,14 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
>>>>         idmap->output_reference = cpu_to_le32(smmu_offset);
>>>>     } else {
>>>>         /* output IORT node is the ITS group node (the first node) */
>>>> -        idmap->output_reference = cpu_to_le32(iort->node_offset);
>>>> +        idmap->output_reference = cpu_to_le32(iort_node_offset);
>>>>     }
>>>>
>>>> +    /*
>>>> +     * Update the pointer address in case table_data->data moves during above
>>>> +     * acpi_data_push operations.
>>>> +     */
>>>> +    iort = (AcpiIortTable *)(table_data->data + iort_start);
>>>>     iort->length = cpu_to_le32(iort_length);
>>>>
>>>>     build_header(linker, table_data, (void *)(table_data->data + iort_start),
>>>
>>> This could just use 'iort' now, right?
>> Right, but for consistent as other places I think it’s fine to remain unchanged. 
>>>
>>>> --
>>>
>>> thanks
>>> -- PMM
>>
>>
> 
> .
> 

-- 
Shannon

  reply	other threads:[~2018-05-30  1:15 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-05-29  3:08 [Qemu-devel] [PATCH v2] ARM: ACPI: Fix use-after-free due to memory realloc Shannon Zhao
2018-05-29 13:53 ` Peter Maydell
2018-05-29 14:09   ` Shannon Zhao
2018-05-29 19:53     ` Auger Eric
2018-05-30  1:14       ` Shannon Zhao [this message]
2018-05-30  6:38         ` Auger Eric
2018-05-30  6:43           ` Shannon Zhao

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=5B0DFB0C.3000002@huawei.com \
    --to=zhaoshenglong@huawei.com \
    --cc=eric.auger@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-arm@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=shannon.zhaosl@gmail.com \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).