Commit 08e3a3a3 authored by Chen Zhongjin's avatar Chen Zhongjin Committed by Xia Fukun
Browse files

firmware: dmi-sysfs: Fix null-ptr-deref in dmi_sysfs_register_handle

mainline inclusion
from mainline-v6.3-rc1
commit 18e126e9
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IBP6BN
CVE: CVE-2022-49370

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18e126e97c961f7a93823795c879d7c085fe5098



--------------------------------

KASAN reported a null-ptr-deref error:

KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
CPU: 0 PID: 1373 Comm: modprobe
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
RIP: 0010:dmi_sysfs_entry_release
...
Call Trace:
 <TASK>
 kobject_put
 dmi_sysfs_register_handle (drivers/firmware/dmi-sysfs.c:540) dmi_sysfs
 dmi_decode_table (drivers/firmware/dmi_scan.c:133)
 dmi_walk (drivers/firmware/dmi_scan.c:1115)
 dmi_sysfs_init (drivers/firmware/dmi-sysfs.c:149) dmi_sysfs
 do_one_initcall (init/main.c:1296)
 ...
Kernel panic - not syncing: Fatal exception
Kernel Offset: 0x4000000 from 0xffffffff81000000
---[ end Kernel panic - not syncing: Fatal exception ]---

It is because previous patch added kobject_put() to release the memory
which will call  dmi_sysfs_entry_release() and list_del().

However, list_add_tail(entry->list) is called after the error block,
so the list_head is uninitialized and cannot be deleted.

Move error handling to after list_add_tail to fix this.

Fixes: 660ba678 ("firmware: dmi-sysfs: Fix memory leak in dmi_sysfs_register_handle")
Signed-off-by: default avatarChen Zhongjin <chenzhongjin@huawei.com>
Link: https://lore.kernel.org/r/20221111015326.251650-2-chenzhongjin@huawei.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarXia Fukun <xiafukun@huawei.com>
parent 994dd5b3
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -601,16 +601,16 @@ static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,
	*ret = kobject_init_and_add(&entry->kobj, &dmi_sysfs_entry_ktype, NULL,
				    "%d-%d", dh->type, entry->instance);

	if (*ret) {
		kobject_put(&entry->kobj);
		return;
	}

	/* Thread on the global list for cleanup */
	spin_lock(&entry_list_lock);
	list_add_tail(&entry->list, &entry_list);
	spin_unlock(&entry_list_lock);

	if (*ret) {
		kobject_put(&entry->kobj);
		return;
	}

	/* Handle specializations by type */
	switch (dh->type) {
	case DMI_ENTRY_SYSTEM_EVENT_LOG: