[PATCH] EDAC/sysfs: Fix UAF in edac_device_register_sysfs_main_kobj()

Guangshuo Li posted 1 patch 1 month, 2 weeks ago
There is a newer version of this series
drivers/edac/edac_device_sysfs.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
[PATCH] EDAC/sysfs: Fix UAF in edac_device_register_sysfs_main_kobj()
Posted by Guangshuo Li 1 month, 2 weeks ago
If kobject_init_and_add() fails, the error path drops the kobject
reference with kobject_put(). This may call
edac_device_ctrl_master_release(), which drops the module reference and
frees the edac_device_ctl_info object.

However, the same error path then calls module_put(edac_dev->owner),
which dereferences edac_dev after it may have been freed. This can cause
a use-after-free and also drops the module reference twice.

Track whether kobject_init_and_add() has been called. If it has, rely on
the kobject release callback to drop the module reference. Otherwise,
drop the module reference directly.

This issue was found by a static analysis tool I am developing.

Fixes: 17ed808ad2431 ("EDAC: Fix reference count leaks")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
 drivers/edac/edac_device_sysfs.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c
index fcebc4ffea26..32460c6dfb7c 100644
--- a/drivers/edac/edac_device_sysfs.c
+++ b/drivers/edac/edac_device_sysfs.c
@@ -231,6 +231,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
 	struct device *dev_root;
 	const struct bus_type *edac_subsys;
 	int err = -ENODEV;
+	bool kobj_initialized = false;
 
 	edac_dbg(1, "\n");
 
@@ -261,6 +262,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
 	if (err) {
 		edac_dbg(1, "Failed to register '.../edac/%s'\n",
 			 edac_dev->name);
+		kobj_initialized = true;
 		goto err_kobj_reg;
 	}
 	kobject_uevent(&edac_dev->kobj, KOBJ_ADD);
@@ -275,8 +277,10 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev)
 
 	/* Error exit stack */
 err_kobj_reg:
-	kobject_put(&edac_dev->kobj);
-	module_put(edac_dev->owner);
+	if (kobj_initialized)
+		kobject_put(&edac_dev->kobj);
+	else
+		module_put(edac_dev->owner);
 
 err_out:
 	return err;
-- 
2.43.0
RE: [PATCH] EDAC/sysfs: Fix UAF in edac_device_register_sysfs_main_kobj()
Posted by Zhuo, Qiuxu 1 month, 2 weeks ago
> From: Guangshuo Li <lgs201920130244@gmail.com>
> [...]
> Subject: [PATCH] EDAC/sysfs: Fix UAF in
> edac_device_register_sysfs_main_kobj()
> 
> If kobject_init_and_add() fails, the error path drops the kobject reference with
> kobject_put(). This may call edac_device_ctrl_master_release(), which drops
> the module reference and frees the edac_device_ctl_info object.
> 
> However, the same error path then calls module_put(edac_dev->owner),
> which dereferences edac_dev after it may have been freed. This can cause a
> use-after-free and also drops the module reference twice.
> 
> Track whether kobject_init_and_add() has been called. If it has, rely on the
> kobject release callback to drop the module reference. Otherwise, drop the
> module reference directly.
> 
> This issue was found by a static analysis tool I am developing.
> 
> Fixes: 17ed808ad2431 ("EDAC: Fix reference count leaks")
> Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
> ---
>  drivers/edac/edac_device_sysfs.c | 8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/edac/edac_device_sysfs.c
> b/drivers/edac/edac_device_sysfs.c
> index fcebc4ffea26..32460c6dfb7c 100644
> --- a/drivers/edac/edac_device_sysfs.c
> +++ b/drivers/edac/edac_device_sysfs.c
> @@ -231,6 +231,7 @@ int edac_device_register_sysfs_main_kobj(struct
> edac_device_ctl_info *edac_dev)
>  	struct device *dev_root;
>  	const struct bus_type *edac_subsys;
>  	int err = -ENODEV;
> +	bool kobj_initialized = false;
> 
>  	edac_dbg(1, "\n");
> 
> @@ -261,6 +262,7 @@ int edac_device_register_sysfs_main_kobj(struct
> edac_device_ctl_info *edac_dev)
>  	if (err) {
>  		edac_dbg(1, "Failed to register '.../edac/%s'\n",
>  			 edac_dev->name);
> +		kobj_initialized = true;

This looks incorrect  - the flag is marked true on failure ???

[...]
Re: [PATCH] EDAC/sysfs: Fix UAF in edac_device_register_sysfs_main_kobj()
Posted by Guangshuo Li 1 month, 2 weeks ago
Hi Zhuo,

Thanks for reviewing.

On Tue, 28 Apr 2026 at 22:33, Zhuo, Qiuxu <qiuxu.zhuo@intel.com> wrote:
>
>
> This looks incorrect  - the flag is marked true on failure ???
>
> [...]

Yes, you're right.

The flag is intended to track whether kobject_init_and_add() has been
called, not whether the function is about to take the error path.

I'll move the assignment to immediately after the kobject_init_and_add()
call, inside the dev_root branch, so the error path only calls
kobject_put() when the kobject has actually been initialized.

Thanks for catching this.