[PATCH 5.4 10/15] firmware: qemu_fw_cfg: fix NULL-pointer deref on duplicate entries
From: Greg Kroah-Hartman
Date: Tue Jan 18 2022 - 11:06:49 EST
From: Johan Hovold <johan@xxxxxxxxxx>
commit d3e305592d69e21e36b76d24ca3c01971a2d09be upstream.
Commit fe3c60684377 ("firmware: Fix a reference count leak.") "fixed"
a kobject leak in the file registration helper by properly calling
kobject_put() for the entry in case registration of the object fails
(e.g. due to a name collision).
This would however result in a NULL pointer dereference when the
release function tries to remove the never added entry from the
fw_cfg_entry_cache list.
Fix this by moving the list-removal out of the release function.
Note that the offending commit was one of the benign looking umn.edu
fixes which was reviewed but not reverted. [1][2]
[1] https://lore.kernel.org/r/202105051005.49BFABCE@keescook
[2] https://lore.kernel.org/all/YIg7ZOZvS3a8LjSv@xxxxxxxxx
Fixes: fe3c60684377 ("firmware: Fix a reference count leak.")
Cc: stable@xxxxxxxxxxxxxxx # 5.8
Cc: Qiushi Wu <wu000273@xxxxxxx>
Cc: Kees Cook <keescook@xxxxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Johan Hovold <johan@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20211201132528.30025-2-johan@xxxxxxxxxx
Signed-off-by: Michael S. Tsirkin <mst@xxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/firmware/qemu_fw_cfg.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -385,9 +385,7 @@ static void fw_cfg_sysfs_cache_cleanup(v
struct fw_cfg_sysfs_entry *entry, *next;
list_for_each_entry_safe(entry, next, &fw_cfg_entry_cache, list) {
- /* will end up invoking fw_cfg_sysfs_cache_delist()
- * via each object's release() method (i.e. destructor)
- */
+ fw_cfg_sysfs_cache_delist(entry);
kobject_put(&entry->kobj);
}
}
@@ -445,7 +443,6 @@ static void fw_cfg_sysfs_release_entry(s
{
struct fw_cfg_sysfs_entry *entry = to_entry(kobj);
- fw_cfg_sysfs_cache_delist(entry);
kfree(entry);
}