[PATCH 1/2] hw/loongarch/boot: Check memory boundary in init_boot_rom()
Bibo Mao <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
When booting the Linux kernel without UEFI BIOS, QEMU needs to set the boot param for kernel. For the LoongArch Linux kernel, it is put in structure loongarch_boot_info, and the total size is 1MB. Here add memory boundary checking with preparing kernel boot param in loongarch_boot_info. Signed-off-by: Bibo Mao <[email protected]> --- hw/loongarch/boot.c | 68 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/hw/loongarch/boot.c b/hw/loongarch/boot.c index ef8eae237c..fe91ab16bd 100644 --- a/hw/loongarch/boot.c +++ b/hw/loongarch/boot.c @@ -173,12 +173,19 @@ static void init_efi_fdt_table(struct efi_system_table *systab) systab->nr_tables = 3; } -static void init_systab(MachineState *ms, +static void init_systab(MachineState *ms, size_t size, struct loongarch_boot_info *info, void *p, void *start) { void *bp_tables_start; struct efi_system_table *systab = p; LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms); + size_t len; + + len = ROUND_UP(sizeof(struct efi_system_table), 64 * KiB); + if (len > size) { + error_report("could not init efi_system_table"); + exit(1); + } info->a2 = p - start; @@ -190,29 +197,56 @@ static void init_systab(MachineState *ms, systab->boottime = 0; systab->nr_tables = 0; - p += ROUND_UP(sizeof(struct efi_system_table), 64 * KiB); + p += len; + size -= len; systab->tables = p; bp_tables_start = p; + len = ROUND_UP(sizeof(struct efi_boot_memmap) + + sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB); + if (len > size) { + error_report("could not init efi_boot_memmap"); + exit(1); + } + init_efi_boot_memmap(ms, systab, p, start); - p += ROUND_UP(sizeof(struct efi_boot_memmap) + - sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB); + p += len; + size -= len; + + len = ROUND_UP(sizeof(struct efi_initrd), 64 * KiB); + if (len > size) { + error_report("could not init efi_initrd"); + exit(1); + } + init_efi_initrd_table(info, systab, p, start); - p += ROUND_UP(sizeof(struct efi_initrd), 64 * KiB); + p += len; + size -= len; init_efi_fdt_table(systab); systab->tables = (struct efi_configuration_table *)(bp_tables_start - start); } -static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start) +static size_t init_cmdline(struct loongarch_boot_info *info, void *p, + void *start, size_t size) { hwaddr cmdline_addr = p - start; + size_t len; info->a0 = 1; info->a1 = cmdline_addr; - g_strlcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE); + len = g_strlcpy(p, info->kernel_cmdline, size); + + /* include terminating null byte */ + if (len < size) { + len += 1; + } else { + len = size; + } + + return len; } static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr) @@ -385,15 +419,21 @@ static void loongarch_firmware_boot(LoongArchVirtMachineState *lvms, fw_cfg_add_kernel_info(info, lvms->fw_cfg); } -static void init_boot_rom(MachineState *ms, +static void init_boot_rom(MachineState *ms, size_t size, struct loongarch_boot_info *info, void *p) { void *start = p; + size_t len; - init_cmdline(info, p, start); - p += COMMAND_LINE_SIZE; + len = init_cmdline(info, p, start, size); + len = ROUND_UP(len, 64 * KiB); + if (len > size) { + error_report("could not init systab"); + exit(1); + } - init_systab(ms, info, p, start); + p += len; + init_systab(ms, size - len, info, p, start); } static void loongarch_direct_kernel_boot(MachineState *ms, @@ -403,6 +443,7 @@ static void loongarch_direct_kernel_boot(MachineState *ms, void *p, *bp; int64_t kernel_addr = VIRT_FLASH0_BASE; uint64_t *data; + size_t size; if (info->kernel_filename) { kernel_addr = load_kernel_info(info, phys_addr_mask); @@ -415,8 +456,9 @@ static void loongarch_direct_kernel_boot(MachineState *ms, /* Load cmdline and system tables at [0 - 1 MiB] */ p = g_malloc0(1 * MiB); bp = p; - init_boot_rom(ms, info, p); - rom_add_blob_fixed_as("boot_info", bp, 1 * MiB, 0, &address_space_memory); + size = 1 * MiB; + init_boot_rom(ms, size, info, p); + rom_add_blob_fixed_as("boot_info", bp, size, 0, &address_space_memory); /* Load slave boot code at pflash0 . */ void *boot_code = g_malloc0(VIRT_FLASH0_SIZE); -- 2.54.0