提交 5601be3b 编写于 作者: P Peter Maydell

exec.c: Don't reallocate IOMMUNotifiers that are in use

The tcg_register_iommu_notifier() code has a GArray of
TCGIOMMUNotifier structs which it has registered by passing
memory_region_register_iommu_notifier() a pointer to the embedded
IOMMUNotifier field. Unfortunately, if we need to enlarge the
array via g_array_set_size() this can cause a realloc(), which
invalidates the pointer that memory_region_register_iommu_notifier()
put into the MemoryRegion's iommu_notify list. This can result
in segfaults.

Switch the GArray to holding pointers to the TCGIOMMUNotifier
structs, so that we can individually allocate and free them.

Cc: qemu-stable@nongnu.org
Fixes: 1f871c5e ("exec.c: Handle IOMMUs in address_space_translate_for_iotlb()")
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: NRichard Henderson <richard.henderson@linaro.org>
Message-id: 20190128174241.5860-1-peter.maydell@linaro.org
上级 4977986c
...@@ -665,7 +665,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu, ...@@ -665,7 +665,7 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
int i; int i;
for (i = 0; i < cpu->iommu_notifiers->len; i++) { for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) { if (notifier->mr == mr && notifier->iommu_idx == iommu_idx) {
break; break;
} }
...@@ -673,7 +673,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu, ...@@ -673,7 +673,8 @@ static void tcg_register_iommu_notifier(CPUState *cpu,
if (i == cpu->iommu_notifiers->len) { if (i == cpu->iommu_notifiers->len) {
/* Not found, add a new entry at the end of the array */ /* Not found, add a new entry at the end of the array */
cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1); cpu->iommu_notifiers = g_array_set_size(cpu->iommu_notifiers, i + 1);
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); notifier = g_new0(TCGIOMMUNotifier, 1);
g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i) = notifier;
notifier->mr = mr; notifier->mr = mr;
notifier->iommu_idx = iommu_idx; notifier->iommu_idx = iommu_idx;
...@@ -705,8 +706,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu) ...@@ -705,8 +706,9 @@ static void tcg_iommu_free_notifier_list(CPUState *cpu)
TCGIOMMUNotifier *notifier; TCGIOMMUNotifier *notifier;
for (i = 0; i < cpu->iommu_notifiers->len; i++) { for (i = 0; i < cpu->iommu_notifiers->len; i++) {
notifier = &g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier, i); notifier = g_array_index(cpu->iommu_notifiers, TCGIOMMUNotifier *, i);
memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n); memory_region_unregister_iommu_notifier(notifier->mr, &notifier->n);
g_free(notifier);
} }
g_array_free(cpu->iommu_notifiers, true); g_array_free(cpu->iommu_notifiers, true);
} }
...@@ -976,7 +978,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp) ...@@ -976,7 +978,7 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu); vmstate_register(NULL, cpu->cpu_index, cc->vmsd, cpu);
} }
cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier)); cpu->iommu_notifiers = g_array_new(false, true, sizeof(TCGIOMMUNotifier *));
#endif #endif
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册