mm/early_ioremap: add null pointer checks to prevent NULL-pointer dereference
The early_ioremap interface can fail and return NULL in certain cases. To prevent NULL-pointer dereference crashes, fixed issues in the acpi_extlog and copy_early_mem interfaces, improving robustness when handling early memory. Link: https://lkml.kernel.org/r/20241212101004.1544070-1-guoweikang.kernel@gmail.com Signed-off-by: Guo Weikang <guoweikang.kernel@gmail.com> Cc: Ard Biesheuvel <ardb@kernel.org> Cc: Arnd Bergmann <arnd@arndb.de> Cc: Baoquan He <bhe@redhat.com> Cc: Borislav Petkov (AMD) <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jason A. Donenfeld <Jason@zx2c4.com> Cc: Julian Stecklina <julian.stecklina@cyberus-technology.de> Cc: Kevin Loughlin <kevinloughlin@google.com> Cc: Len Brown <lenb@kernel.org> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Cc: "Rafael J. Wysocki" <rafael@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Xin Li (Intel) <xin@zytor.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
8ad946eb3d
commit
ccd582059a
4 changed files with 26 additions and 3 deletions
|
@ -259,6 +259,7 @@ static void __init relocate_initrd(void)
|
|||
u64 ramdisk_image = get_ramdisk_image();
|
||||
u64 ramdisk_size = get_ramdisk_size();
|
||||
u64 area_size = PAGE_ALIGN(ramdisk_size);
|
||||
int ret = 0;
|
||||
|
||||
/* We need to move the initrd down into directly mapped mem */
|
||||
u64 relocated_ramdisk = memblock_phys_alloc_range(area_size, PAGE_SIZE, 0,
|
||||
|
@ -272,7 +273,9 @@ static void __init relocate_initrd(void)
|
|||
printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
|
||||
relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
|
||||
|
||||
copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
|
||||
ret = copy_from_early_mem((void *)initrd_start, ramdisk_image, ramdisk_size);
|
||||
if (ret)
|
||||
panic("Copy RAMDISK failed\n");
|
||||
|
||||
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
|
||||
" [mem %#010llx-%#010llx]\n",
|
||||
|
|
|
@ -251,6 +251,10 @@ static int __init extlog_init(void)
|
|||
}
|
||||
|
||||
extlog_l1_hdr = acpi_os_map_iomem(l1_dirbase, l1_hdr_size);
|
||||
if (!extlog_l1_hdr) {
|
||||
rc = -ENOMEM;
|
||||
goto err_release_l1_hdr;
|
||||
}
|
||||
l1_head = (struct extlog_l1_head *)extlog_l1_hdr;
|
||||
l1_size = l1_head->total_len;
|
||||
l1_percpu_entry = l1_head->entries;
|
||||
|
@ -268,6 +272,10 @@ static int __init extlog_init(void)
|
|||
goto err;
|
||||
}
|
||||
extlog_l1_addr = acpi_os_map_iomem(l1_dirbase, l1_size);
|
||||
if (!extlog_l1_addr) {
|
||||
rc = -ENOMEM;
|
||||
goto err_release_l1_dir;
|
||||
}
|
||||
l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size);
|
||||
|
||||
/* remap elog table */
|
||||
|
@ -279,6 +287,10 @@ static int __init extlog_init(void)
|
|||
goto err_release_l1_dir;
|
||||
}
|
||||
elog_addr = acpi_os_map_iomem(elog_base, elog_size);
|
||||
if (!elog_addr) {
|
||||
rc = -ENOMEM;
|
||||
goto err_release_elog;
|
||||
}
|
||||
|
||||
rc = -ENOMEM;
|
||||
/* allocate buffer to save elog record */
|
||||
|
@ -300,6 +312,8 @@ err_release_l1_dir:
|
|||
if (extlog_l1_addr)
|
||||
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
|
||||
release_mem_region(l1_dirbase, l1_size);
|
||||
err_release_l1_hdr:
|
||||
release_mem_region(l1_dirbase, l1_hdr_size);
|
||||
err:
|
||||
pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n");
|
||||
return rc;
|
||||
|
|
|
@ -35,7 +35,7 @@ extern void early_ioremap_reset(void);
|
|||
/*
|
||||
* Early copy from unmapped memory to kernel mapped memory.
|
||||
*/
|
||||
extern void copy_from_early_mem(void *dest, phys_addr_t src,
|
||||
extern int copy_from_early_mem(void *dest, phys_addr_t src,
|
||||
unsigned long size);
|
||||
|
||||
#else
|
||||
|
|
|
@ -245,7 +245,10 @@ early_memremap_prot(resource_size_t phys_addr, unsigned long size,
|
|||
|
||||
#define MAX_MAP_CHUNK (NR_FIX_BTMAPS << PAGE_SHIFT)
|
||||
|
||||
void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
|
||||
/*
|
||||
* If no empty slot, handle that and return -ENOMEM.
|
||||
*/
|
||||
int __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
|
||||
{
|
||||
unsigned long slop, clen;
|
||||
char *p;
|
||||
|
@ -256,12 +259,15 @@ void __init copy_from_early_mem(void *dest, phys_addr_t src, unsigned long size)
|
|||
if (clen > MAX_MAP_CHUNK - slop)
|
||||
clen = MAX_MAP_CHUNK - slop;
|
||||
p = early_memremap(src & PAGE_MASK, clen + slop);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
memcpy(dest, p + slop, clen);
|
||||
early_memunmap(p, clen + slop);
|
||||
dest += clen;
|
||||
src += clen;
|
||||
size -= clen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* CONFIG_MMU */
|
||||
|
|
Loading…
Add table
Reference in a new issue