Message ID | 1527496946-12036-1-git-send-email-zhaoshenglong@huawei.com |
---|---|
State | New |
Headers | show |
Series | ARM: ACPI: Fix use-after-free due to memory realloc | expand |
Hi Shannon, On 05/28/2018 10:42 AM, Shannon Zhao 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. > > Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> Reviewed-by: Eric Auger <eric.auger@redhat.com> Thanks! Eric > --- > hw/arm/virt-acpi-build.c | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > index 92ceee9..30584ee 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)); > @@ -414,6 +414,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) > iort_length = sizeof(*iort); > iort->node_count = cpu_to_le32(nb_nodes); > iort->node_offset = cpu_to_le32(sizeof(*iort)); > + iort_node_offset = iort->node_offset; > > /* ITS group node */ > node_size = sizeof(*its) + sizeof(uint32_t); > @@ -429,7 +430,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; > node_size = sizeof(*smmu) + sizeof(*idmap); > iort_length += node_size; > smmu = acpi_data_push(table_data, node_size); > @@ -450,7 +451,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); > } > > /* Root Complex Node */ > @@ -479,9 +480,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 moved 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), >
On 05/28/2018 05:42 AM, Shannon Zhao 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. > > Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> > --- > hw/arm/virt-acpi-build.c | 14 ++++++++++---- > 1 file changed, 10 insertions(+), 4 deletions(-) > > diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c > index 92ceee9..30584ee 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)); > @@ -414,6 +414,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) > iort_length = sizeof(*iort); > iort->node_count = cpu_to_le32(nb_nodes); > iort->node_offset = cpu_to_le32(sizeof(*iort)); Eventually similar comment to explain why you also use another var: /* * Use a copy in case table_data->data moves during * acpi_data_push operations. */ > + iort_node_offset = iort->node_offset; Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> > > /* ITS group node */ > node_size = sizeof(*its) + sizeof(uint32_t); > @@ -429,7 +430,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; > node_size = sizeof(*smmu) + sizeof(*idmap); > iort_length += node_size; > smmu = acpi_data_push(table_data, node_size); > @@ -450,7 +451,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); > } > > /* Root Complex Node */ > @@ -479,9 +480,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 moved 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), >
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 92ceee9..30584ee 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)); @@ -414,6 +414,7 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) iort_length = sizeof(*iort); iort->node_count = cpu_to_le32(nb_nodes); iort->node_offset = cpu_to_le32(sizeof(*iort)); + iort_node_offset = iort->node_offset; /* ITS group node */ node_size = sizeof(*its) + sizeof(uint32_t); @@ -429,7 +430,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; node_size = sizeof(*smmu) + sizeof(*idmap); iort_length += node_size; smmu = acpi_data_push(table_data, node_size); @@ -450,7 +451,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); } /* Root Complex Node */ @@ -479,9 +480,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 moved 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),
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. Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com> --- hw/arm/virt-acpi-build.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)