Commit ccd58205 authored by Guo Weikang's avatar Guo Weikang Committed by Andrew Morton
Browse files

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: default avatarGuo 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: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 8ad946eb
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -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",
+14 −0
Original line number Diff line number Diff line
@@ -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 @@ static int __init extlog_init(void)
	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;
+1 −1
Original line number Diff line number Diff line
@@ -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
+7 −1
Original line number Diff line number Diff line
@@ -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 */