mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
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
@ -259,6 +259,7 @@ static void __init relocate_initrd(void)
|
|||||||
u64 ramdisk_image = get_ramdisk_image();
|
u64 ramdisk_image = get_ramdisk_image();
|
||||||
u64 ramdisk_size = get_ramdisk_size();
|
u64 ramdisk_size = get_ramdisk_size();
|
||||||
u64 area_size = PAGE_ALIGN(ramdisk_size);
|
u64 area_size = PAGE_ALIGN(ramdisk_size);
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
/* We need to move the initrd down into directly mapped mem */
|
/* We need to move the initrd down into directly mapped mem */
|
||||||
u64 relocated_ramdisk = memblock_phys_alloc_range(area_size, PAGE_SIZE, 0,
|
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",
|
printk(KERN_INFO "Allocated new RAMDISK: [mem %#010llx-%#010llx]\n",
|
||||||
relocated_ramdisk, relocated_ramdisk + ramdisk_size - 1);
|
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"
|
printk(KERN_INFO "Move RAMDISK from [mem %#010llx-%#010llx] to"
|
||||||
" [mem %#010llx-%#010llx]\n",
|
" [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);
|
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_head = (struct extlog_l1_head *)extlog_l1_hdr;
|
||||||
l1_size = l1_head->total_len;
|
l1_size = l1_head->total_len;
|
||||||
l1_percpu_entry = l1_head->entries;
|
l1_percpu_entry = l1_head->entries;
|
||||||
@ -268,6 +272,10 @@ static int __init extlog_init(void)
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
extlog_l1_addr = acpi_os_map_iomem(l1_dirbase, l1_size);
|
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);
|
l1_entry_base = (u64 *)((u8 *)extlog_l1_addr + l1_hdr_size);
|
||||||
|
|
||||||
/* remap elog table */
|
/* remap elog table */
|
||||||
@ -279,6 +287,10 @@ static int __init extlog_init(void)
|
|||||||
goto err_release_l1_dir;
|
goto err_release_l1_dir;
|
||||||
}
|
}
|
||||||
elog_addr = acpi_os_map_iomem(elog_base, elog_size);
|
elog_addr = acpi_os_map_iomem(elog_base, elog_size);
|
||||||
|
if (!elog_addr) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto err_release_elog;
|
||||||
|
}
|
||||||
|
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
/* allocate buffer to save elog record */
|
/* allocate buffer to save elog record */
|
||||||
@ -300,6 +312,8 @@ err_release_l1_dir:
|
|||||||
if (extlog_l1_addr)
|
if (extlog_l1_addr)
|
||||||
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
|
acpi_os_unmap_iomem(extlog_l1_addr, l1_size);
|
||||||
release_mem_region(l1_dirbase, l1_size);
|
release_mem_region(l1_dirbase, l1_size);
|
||||||
|
err_release_l1_hdr:
|
||||||
|
release_mem_region(l1_dirbase, l1_hdr_size);
|
||||||
err:
|
err:
|
||||||
pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n");
|
pr_warn(FW_BUG "Extended error log disabled because of problems parsing f/w tables\n");
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -35,7 +35,7 @@ extern void early_ioremap_reset(void);
|
|||||||
/*
|
/*
|
||||||
* Early copy from unmapped memory to kernel mapped memory.
|
* 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);
|
unsigned long size);
|
||||||
|
|
||||||
#else
|
#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)
|
#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;
|
unsigned long slop, clen;
|
||||||
char *p;
|
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)
|
if (clen > MAX_MAP_CHUNK - slop)
|
||||||
clen = MAX_MAP_CHUNK - slop;
|
clen = MAX_MAP_CHUNK - slop;
|
||||||
p = early_memremap(src & PAGE_MASK, clen + slop);
|
p = early_memremap(src & PAGE_MASK, clen + slop);
|
||||||
|
if (!p)
|
||||||
|
return -ENOMEM;
|
||||||
memcpy(dest, p + slop, clen);
|
memcpy(dest, p + slop, clen);
|
||||||
early_memunmap(p, clen + slop);
|
early_memunmap(p, clen + slop);
|
||||||
dest += clen;
|
dest += clen;
|
||||||
src += clen;
|
src += clen;
|
||||||
size -= clen;
|
size -= clen;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* CONFIG_MMU */
|
#else /* CONFIG_MMU */
|
||||||
|
Loading…
Reference in New Issue
Block a user