@samitouri / QOSamiQemu / commits / 8ea09c6284

hw/loongarch/boot: Check memory boundary in init_boot_rom()

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 <maobibo@loongson.cn> Reviewed-by: Song Gao <gaosong@loongson.cn> Message-ID: <20260807070029.1171348-2-maobibo@loongson.cn> Signed-off-by: Song Gao <gaosong@loongson.cn>

Bibo Mao committed Aug 7, 2026 at 15:00 UTC 8ea09c6284c842f0d281651df623b94809ae0349
1 file changed +55 -13
hw/loongarch/boot.c
+55 -13
@@ -173,12 +173,19 @@ static void init_efi_fdt_table(struct efi_system_table *systab)
173 systab->nr_tables = 3;
174 }
175
176 -static void init_systab(MachineState *ms,
176 +static void init_systab(MachineState *ms, size_t size,
177 struct loongarch_boot_info *info, void *p, void *start)
178 {
179 void *bp_tables_start;
180 struct efi_system_table *systab = p;
181 LoongArchVirtMachineState *lvms = LOONGARCH_VIRT_MACHINE(ms);
182 + size_t len;
183 +
184 + len = ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
185 + if (len > size) {
186 + error_report("could not init efi_system_table");
187 + exit(1);
188 + }
189
190 info->a2 = p - start;
191
@@ -190,29 +197,56 @@ static void init_systab(MachineState *ms,
197 systab->boottime = 0;
198 systab->nr_tables = 0;
199
193 - p += ROUND_UP(sizeof(struct efi_system_table), 64 * KiB);
200 + p += len;
201 + size -= len;
202
203 systab->tables = p;
204 bp_tables_start = p;
205
206 + len = ROUND_UP(sizeof(struct efi_boot_memmap) +
207 + sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB);
208 + if (len > size) {
209 + error_report("could not init efi_boot_memmap");
210 + exit(1);
211 + }
212 +
213 init_efi_boot_memmap(ms, systab, p, start);
199 - p += ROUND_UP(sizeof(struct efi_boot_memmap) +
200 - sizeof(efi_memory_desc_t) * lvms->memmap_entries, 64 * KiB);
214 + p += len;
215 + size -= len;
216 +
217 + len = ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
218 + if (len > size) {
219 + error_report("could not init efi_initrd");
220 + exit(1);
221 + }
222 +
223 init_efi_initrd_table(info, systab, p, start);
202 - p += ROUND_UP(sizeof(struct efi_initrd), 64 * KiB);
224 + p += len;
225 + size -= len;
226 init_efi_fdt_table(systab);
227
228 systab->tables = (struct efi_configuration_table *)(bp_tables_start - start);
229 }
230
208 -static void init_cmdline(struct loongarch_boot_info *info, void *p, void *start)
231 +static size_t init_cmdline(struct loongarch_boot_info *info, void *p,
232 + void *start, size_t size)
233 {
234 hwaddr cmdline_addr = p - start;
235 + size_t len;
236
237 info->a0 = 1;
238 info->a1 = cmdline_addr;
239
215 - g_strlcpy(p, info->kernel_cmdline, COMMAND_LINE_SIZE);
240 + len = g_strlcpy(p, info->kernel_cmdline, size);
241 +
242 + /* include terminating null byte */
243 + if (len < size) {
244 + len += 1;
245 + } else {
246 + len = size;
247 + }
248 +
249 + return len;
250 }
251
252 static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
@@ -385,15 +419,21 @@ static void loongarch_firmware_boot(LoongArchVirtMachineState *lvms,
419 fw_cfg_add_kernel_info(info, lvms->fw_cfg);
420 }
421
388 -static void init_boot_rom(MachineState *ms,
422 +static void init_boot_rom(MachineState *ms, size_t size,
423 struct loongarch_boot_info *info, void *p)
424 {
425 void *start = p;
426 + size_t len;
427
393 - init_cmdline(info, p, start);
394 - p += COMMAND_LINE_SIZE;
428 + len = init_cmdline(info, p, start, size);
429 + len = ROUND_UP(len, 64 * KiB);
430 + if (len > size) {
431 + error_report("could not init systab");
432 + exit(1);
433 + }
434
396 - init_systab(ms, info, p, start);
435 + p += len;
436 + init_systab(ms, size - len, info, p, start);
437 }
438
439 static void loongarch_direct_kernel_boot(MachineState *ms,
@@ -403,6 +443,7 @@ static void loongarch_direct_kernel_boot(MachineState *ms,
443 void *p, *bp;
444 int64_t kernel_addr = VIRT_FLASH0_BASE;
445 uint64_t *data;
446 + size_t size;
447
448 if (info->kernel_filename) {
449 kernel_addr = load_kernel_info(info, phys_addr_mask);
@@ -415,8 +456,9 @@ static void loongarch_direct_kernel_boot(MachineState *ms,
456 /* Load cmdline and system tables at [0 - 1 MiB] */
457 p = g_malloc0(1 * MiB);
458 bp = p;
418 - init_boot_rom(ms, info, p);
419 - rom_add_blob_fixed_as("boot_info", bp, 1 * MiB, 0, &address_space_memory);
459 + size = 1 * MiB;
460 + init_boot_rom(ms, size, info, p);
461 + rom_add_blob_fixed_as("boot_info", bp, size, 0, &address_space_memory);
462
463 /* Load slave boot code at pflash0 . */
464 void *boot_code = g_malloc0(VIRT_FLASH0_SIZE);