From: Rahul Rameshbabu <rrameshbabu@nvidia.com>
To: Maxime Ripard <mripard@kernel.org>
Cc: syzbot <syzbot+3a0ebe8a52b89c63739d@syzkaller.appspotmail.com>,
davidgow@google.com, dmitry.torokhov@gmail.com,
gregkh@linuxfoundation.org, linux-input@vger.kernel.org,
linux-kernel@vger.kernel.org, rydberg@bitmath.org,
syzkaller-bugs@googlegroups.com, benjamin.tissoires@redhat.com
Subject: Re: [syzbot] [input?] KASAN: slab-use-after-free Read in input_dev_uevent
Date: Tue, 22 Aug 2023 15:34:27 -0700 [thread overview]
Message-ID: <874jkqn1u4.fsf@nvidia.com> (raw)
In-Reply-To: <878ra3m5my.fsf@nvidia.com> (Rahul Rameshbabu's message of "Tue, 22 Aug 2023 08:57:41 -0700")
On Tue, 22 Aug, 2023 08:57:41 -0700 Rahul Rameshbabu <rrameshbabu@nvidia.com> wrote:
> Hi Maxime,
>
> On Tue, 22 Aug, 2023 11:12:28 +0200 Maxime Ripard <mripard@kernel.org> wrote:
>> Hi,
>>
>> So, we discussed it this morning with Benjamin, and I think the culprit
>> is that the uclogic driver will allocate a char array with devm_kzalloc
>> in uclogic_input_configured()
>> (https://elixir.bootlin.com/linux/latest/source/drivers/hid/hid-uclogic-core.c#L149),
>> and will assign input_dev->name to that pointer.
>>
>> When the device is removed, the devm-allocated array is freed, and the
>> input framework will send a uevent in input_dev_uevent() using the
>> input_dev->name field:
>>
>> https://elixir.bootlin.com/linux/latest/source/drivers/input/input.c#L1688
>>
>> So it's a classic dangling pointer situation.
>>
>> And even though it was revealed by that patch, I think the issue is
>> unrelated. The fundamental issue seems to be that the usage of devm in
>> that situation is wrong.
>>
>> input_dev->name is accessed by input_dev_uevent, which for KOBJ_UNBIND
>> and KOBJ_REMOVE will be called after remove.
>>
>> For example, in __device_release_driver() (with the driver remove hook
>> being called in device_remove() and devres_release_all() being called in
>> device_unbind_cleanup()):
>> https://elixir.bootlin.com/linux/latest/source/drivers/base/dd.c#L1278
>>
>> So, it looks to me that, with or without the patch we merged recently,
>> the core has always sent uevent after device-managed resources were
>> freed. Thus, the uclogic (and any other input driver) was wrong in
>> allocating its input_dev name with devm_kzalloc (or the phys and uniq
>> fields in that struct).
>>
>> Note that freeing input_dev->name in remove would have been just as bad.
>>
>> Looking at the code quickly, at least hid-playstation,
>> hid-nvidia-shield, hid-logitech-hidpp, mms114 and tsc200x seem to be
>> affected by the same issue.
>
> I agree with this analysis overall. At least in hid-nvidia-shield, I can
> not use devm for allocating the input name string and explicitly free it
> after calling input_unregister_device. In this scenario, the name string
> would have been freed explicitly after input_put_device was called
> (since the input device is not devres managed). input_put_device would
> drop the reference count to zero and the device would be cleaned up at
> that point triggering KOBJ_REMOVE and firing off that final
> input_dev_uevent.
>
> I think this can be done for a number of the drivers as a workaround
> till this issue is properly resolved. If this seems appropriate, I can
> send out a series later in the day. This is just a workaround till the
> discussion below converges (which I am interested in).
After thinking about it a bit further, I believe hid-nvidia-shield is
not impacted by this issue in its current state. hid_hw_stop will
trigger devres_release_all, which will free the input name allocated.
This is problematic in the case that the input_dev is devres managed,
since device resource management will hook the uevent callback on
device_del triggered by input_unregister_device invoked by hid_hw_stop.
However, hid-nvidia-shield does not use devm to allocate the input
device and explicitly calls input_unregister_device before the call to
hid_hw_stop. I believe this leads to the uevent being fired before name
is freed by devres after the hid_hw_stop call. Let me know if this
analysis seems off. Hoping this can be helpful in general if this is the
case.
Freed by task 4508:
kasan_save_stack+0x33/0x50 mm/kasan/common.c:45
kasan_set_track+0x25/0x30 mm/kasan/common.c:52
kasan_save_free_info+0x2b/0x40 mm/kasan/generic.c:522
____kasan_slab_free mm/kasan/common.c:236 [inline]
____kasan_slab_free+0x15b/0x1b0 mm/kasan/common.c:200
kasan_slab_free include/linux/kasan.h:164 [inline]
slab_free_hook mm/slub.c:1800 [inline]
slab_free_freelist_hook+0x114/0x1e0 mm/slub.c:1826
slab_free mm/slub.c:3809 [inline]
__kmem_cache_free+0xb8/0x2f0 mm/slub.c:3822
release_nodes drivers/base/devres.c:506 [inline]
devres_release_all+0x192/0x240 drivers/base/devres.c:535
device_del+0x628/0xa50 drivers/base/core.c:3827
input_unregister_device+0xb9/0x100 drivers/input/input.c:2440
hidinput_disconnect+0x160/0x3e0 drivers/hid/hid-input.c:2386
hid_disconnect+0x143/0x1b0 drivers/hid/hid-core.c:2273
hid_hw_stop+0x16/0x70 drivers/hid/hid-core.c:2322
uclogic_remove+0x47/0x90 drivers/hid/hid-uclogic-core.c:485
>
>>
>> We discussed a couple of solutions with Benjamin, such as creating a
>> helper devm action to free and clear the input_dev->name field, droping
>> the name, phys and uniq fields from the uevent, or converting name, phys
>> and uniq to char arrays so drivers don't have to allocate them.
>>
>> We couldn't find a perfect one though, so... yeah.
>>
>> Maxime
>
--
Thanks,
Rahul Rameshbabu
next prev parent reply other threads:[~2023-08-22 22:34 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-21 16:48 [syzbot] [input?] KASAN: slab-use-after-free Read in input_dev_uevent syzbot
2023-08-22 9:12 ` Maxime Ripard
2023-08-22 15:57 ` Rahul Rameshbabu
2023-08-22 22:34 ` Rahul Rameshbabu [this message]
2023-08-23 7:44 ` Maxime Ripard
2023-08-23 12:51 ` Dmitry Torokhov
2023-08-23 13:16 ` Maxime Ripard
2023-08-23 14:55 ` Dmitry Torokhov
2023-08-23 16:30 ` Maxime Ripard
2023-08-23 17:04 ` Rahul Rameshbabu
2023-08-23 17:56 ` Dmitry Torokhov
[not found] <20230822115844.2776-1-hdanton@sina.com>
2023-08-22 13:49 ` syzbot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=874jkqn1u4.fsf@nvidia.com \
--to=rrameshbabu@nvidia.com \
--cc=benjamin.tissoires@redhat.com \
--cc=davidgow@google.com \
--cc=dmitry.torokhov@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-input@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mripard@kernel.org \
--cc=rydberg@bitmath.org \
--cc=syzbot+3a0ebe8a52b89c63739d@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox