[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200405164006.GA1582475@kroah.com>
Date: Sun, 5 Apr 2020 18:40:06 +0200
From: Greg KH <gregkh@...uxfoundation.org>
To: zhangfeionline@...il.com
Cc: rafael@...nel.org, linux-kernel@...r.kernel.org,
songmuchun@...edance.com
Subject: Re: [PATCH] driver core: Fix possible use after free on name
On Sun, Apr 05, 2020 at 09:05:49AM -0700, zhangfeionline@...il.com wrote:
> From: PengfeiZhang <zhangfeionline@...il.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.
Where are you seeing this happen?
>
> Signed-off-by: PengfeiZhang <zhangfeionline@...il.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;
This is a new change, who calls this function with name not being set?
>
> 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;
> + }
and overwriting the pointer like that is bad-form, try doing something
else here instead.
> +
> 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);
kfree_const()?
thanks,
greg k-h
Powered by blists - more mailing lists