Skip to contentSkip to conversation

driver core: faux: fix root device registration

PATCH Superseded Johan Hovold 3 participants 4 messages Apr 24

Subsystems (2)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Johan Hovold

author maintainer
#0 lore raw

PATCH 1/1 driver core: faux: fix root device registration

A recent change made the faux bus root device be allocated dynamically but failed to provide a release function to free the memory when the last reference is dropped (on theoretical failure to register the device or bus).

Fix this by using root_device_register() instead of open coding.

Also add the missing sanity check when registering faux devices to avoid a NULL-pointer dereference if the bus failed to register (which would previously have triggered a bunch of use-after-free warnings).

Fixes 61b76d07d2b4 ("driver core: faux: stop using static struct device")
Cc Greg Kroah-Hartman <[email protected]>
---
 drivers/base/faux.c | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)
drivers/base/faux.c +7 -12
index fb3e42f21362..402ed119dfdf 100644
@@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
 	struct device *dev;
 	int ret;
 
+	if (IS_ERR_OR_NULL(faux_bus_root))
+		return NULL;
+
 	faux_obj = kzalloc_obj(*faux_obj);
 	if (!faux_obj)
 		return NULL;
@@ -234,17 +237,9 @@ int __init faux_bus_init(void)
 {
 	int ret;
 
-	faux_bus_root = kzalloc_obj(*faux_bus_root);
-	if (!faux_bus_root)
-		return -ENOMEM;
-
-	dev_set_name(faux_bus_root, "faux");
-
-	ret = device_register(faux_bus_root);
-	if (ret) {
-		put_device(faux_bus_root);
-		return ret;
-	}
+	faux_bus_root = root_device_register("faux");
+	if (IS_ERR(faux_bus_root))
+		return PTR_ERR(faux_bus_root);
 
 	ret = bus_register(&faux_bus_type);
 	if (ret)
@@ -260,6 +255,6 @@ int __init faux_bus_init(void)
 	bus_unregister(&faux_bus_type);
 
 error_bus:
-	device_unregister(faux_bus_root);
+	root_device_unregister(faux_bus_root);
 	return ret;
 }
Signature · 1 line
2.53.0
#1 lore raw
Quoted 6 lines · Johan Hovold

A recent change made the faux bus root device be allocated dynamically but failed to provide a release function to free the memory when the last reference is dropped (on theoretical failure to register the device or bus).

Fix this by using root_device_register() instead of open coding.

Ah, good catch, I missed that, thanks!

Quoted 3 lines

Also add the missing sanity check when registering faux devices to avoid a NULL-pointer dereference if the bus failed to register (which would previously have triggered a bunch of use-after-free warnings).

If the bus fails to register at boot time, we have bigger problems than those types of warnings :)

I'll queue this up after -rc1 is out, thanks.

greg k-h

maintainer
#2 lore raw
In reply to Johan Hovold

drivers/base/faux.c struct faux_device *faux_device_create_with_groups(const char *name, · line 137

Quoted 10 lines · Johan Hovold
drivers/base/faux.c +2 -0
index fb3e42f21362..402ed119dfdf 100644
@@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
 	struct device *dev;
 	int ret;
 
+	if (IS_ERR_OR_NULL(faux_bus_root))
+		return NULL;

As Greg mentioned, if this happens we already have a much bigger fundamental problem earlier in the boot process.

Anyway, I think this check only catches when root_device_register() fails, but everything that comes after root_device_register() in faux_bus_init() still leaves us with a dangling pointer.

Quoted 35 lines
drivers/base/faux.c +5 -12
+
 	faux_obj = kzalloc_obj(*faux_obj);
 	if (!faux_obj)
 		return NULL;
@@ -234,17 +237,9 @@ int __init faux_bus_init(void)
 {
 	int ret;
 
-	faux_bus_root = kzalloc_obj(*faux_bus_root);
-	if (!faux_bus_root)
-		return -ENOMEM;
-
-	dev_set_name(faux_bus_root, "faux");
-
-	ret = device_register(faux_bus_root);
-	if (ret) {
-		put_device(faux_bus_root);
-		return ret;
-	}
+	faux_bus_root = root_device_register("faux");
+	if (IS_ERR(faux_bus_root))
+		return PTR_ERR(faux_bus_root);
 
 	ret = bus_register(&faux_bus_type);
 	if (ret)
@@ -260,6 +255,6 @@ int __init faux_bus_init(void)
 	bus_unregister(&faux_bus_type);
 
 error_bus:
-	device_unregister(faux_bus_root);
+	root_device_unregister(faux_bus_root);
 	return ret;
 }
Signature · 1 line
2.53.0
author maintainer
#3 lore raw
Quoted 15 lines · Danilo Krummrich

drivers/base/faux.c struct faux_device *faux_device_create_with_groups(const char *name, · line 137

Quoted 10 lines · Johan Hovold
drivers/base/faux.c +2 -0
index fb3e42f21362..402ed119dfdf 100644
@@ -133,6 +133,9 @@ struct faux_device *faux_device_create_with_groups(const char *name,
 	struct device *dev;
 	int ret;
 
+	if (IS_ERR_OR_NULL(faux_bus_root))
+		return NULL;

As Greg mentioned, if this happens we already have a much bigger fundamental problem earlier in the boot process.

Quoted 3 lines

Anyway, I think this check only catches when root_device_register() fails, but everything that comes after root_device_register() in faux_bus_init() still leaves us with a dangling pointer.

Indeed. I cleared the pointer in an earlier draft for this reason, but got side tracked and later found the change too invasive for something that would never happen in practise and somehow convinced myself that this check would do.

I'll respin.

Johan