[PATCH] driver core: Fix possible use after free on name

zhangfeionline
2020-04-05T16:06:33Z

From: PengfeiZhang <zhangfeionline@gmail.com>

__class_create() copies the pointer to the name passed as an
argument only to be used later. But there's a chance the caller
could immediately free the passed string(e.g., local variable).
This could trigger a use after free when we use class name(e.g.,
dev_uevent_name()called by device_destroy(),class_create_release()).

To be on the safe side: duplicate the string with kstrdup_const()
so that if an unaware user passes an address to a stack-allocated
buffer, we won't get the arbitrary name and crash.

Signed-off-by: PengfeiZhang <zhangfeionline@gmail.com>
---
drivers/base/class.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/base/class.c b/drivers/base/class.c
index bcd410e..770b3b3 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -206,6 +206,7 @@ void class_unregister(struct class *cls)
static void class_create_release(struct class *cls)
{
pr_debug("%s called for %s\n", __func__, cls->name);
+ kfree_const(cls->name);
kfree(cls);
}

@@ -227,7 +228,10 @@ struct class *__class_create(struct module *owner, const char *name,
struct lock_class_key *key)
{
struct class *cls;
- int retval;
+ int retval = -EINVAL;
+
+ if (!name)
+ goto done;

cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
@@ -235,18 +239,27 @@ struct class *__class_create(struct module *owner, const char *name,
goto error;
}

+ name = kstrdup_const(name, GFP_KERNEL);
+ if (!name) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
cls->name = name;
cls->owner = owner;
cls->class_release = class_create_release;

retval = __class_register(cls, key);
if (retval)
- goto error;
+ goto error_class_register;

return cls;

+error_class_register:
+ kfree(cls->name);
error:
kfree(cls);
+done:
return ERR_PTR(retval);
}
EXPORT_SYMBOL_GPL(__class_create);
--
2.7.4