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);