qemu/hw/i386/e820_memory_layout.c
David Woodhouse 93c76555d8 hw/i386/fw_cfg: Add etc/e820 to fw_cfg late
In e820_add_entry() the e820_table is reallocated with g_renew() to make
space for a new entry. However, fw_cfg_arch_create() just uses the
existing e820_table pointer. This leads to a use-after-free if anything
adds a new entry after fw_cfg is set up.

Shift the addition of the etc/e820 file to the machine done notifier, via
a new fw_cfg_add_e820() function.

Also make e820_table private and use an e820_get_table() accessor function
for it, which sets a flag that will trigger an assert() for any *later*
attempts to add to the table.

Make e820_add_entry() return void, as most callers don't check for error
anyway.

Signed-off-by: David Woodhouse <dwmw@amazon.co.uk>
Message-Id: <a2708734f004b224f33d3b4824e9a5a262431568.camel@infradead.org>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
2024-07-03 18:14:06 -04:00

49 lines
1.2 KiB
C

/*
* QEMU BIOS e820 routines
*
* Copyright (c) 2003-2004 Fabrice Bellard
*
* SPDX-License-Identifier: MIT
*/
#include "qemu/osdep.h"
#include "qemu/bswap.h"
#include "e820_memory_layout.h"
static size_t e820_entries;
static struct e820_entry *e820_table;
static gboolean e820_done;
void e820_add_entry(uint64_t address, uint64_t length, uint32_t type)
{
assert(!e820_done);
/* new "etc/e820" file -- include ram and reserved entries */
e820_table = g_renew(struct e820_entry, e820_table, e820_entries + 1);
e820_table[e820_entries].address = cpu_to_le64(address);
e820_table[e820_entries].length = cpu_to_le64(length);
e820_table[e820_entries].type = cpu_to_le32(type);
e820_entries++;
}
int e820_get_table(struct e820_entry **table)
{
e820_done = true;
if (table) {
*table = e820_table;
}
return e820_entries;
}
bool e820_get_entry(int idx, uint32_t type, uint64_t *address, uint64_t *length)
{
if (idx < e820_entries && e820_table[idx].type == cpu_to_le32(type)) {
*address = le64_to_cpu(e820_table[idx].address);
*length = le64_to_cpu(e820_table[idx].length);
return true;
}
return false;
}