From: David Lee <david.lee@trailofbits.com>
To: Lee Jones <lee@kernel.org>
Cc: David Lee <david.lee@trailofbits.com>,
Pavel Machek <pavel@kernel.org>,
Dominik 'Disconnect3d' Czarnota
<dominik.czarnota@trailofbits.com>,
linux-leds@vger.kernel.org, linux-kernel@vger.kernel.org,
stable@vger.kernel.org
Subject: [PATCH] leds: class: disable sysfs before unregistering LED devices
Date: Thu, 9 Jul 2026 10:12:08 +0000 [thread overview]
Message-ID: <20260709101210.104975-1-david.lee@trailofbits.com> (raw)
Closing a uleds device removes the LED class device and then frees the
struct uleds_device that contains it. The LED class device is also exposed
through sysfs, where attributes such as trigger, brightness, delay_on, and
delay_off can remain open across unregister.
That creates a lifetime race. led_classdev_unregister() tears down the LED
trigger, software blink timer, brightness state, and trigger-specific sysfs
groups, but it does not first block LED sysfs writers. An already-open sysfs
attribute can therefore enter the LED trigger or timer paths while unregister
is tearing down the same embedded struct led_classdev.
For uleds this can become a use-after-free: after unregister returns,
uleds_release() frees the containing struct uleds_device, while stale sysfs
or timer paths may still access led_classdev fields embedded in that freed
object. KASAN reports use-after-free reads and writes in __run_timers(),
led_timer_function(), and uleds_brightness_set().
Fix this by entering the existing LED sysfs exclusion protocol at the start
of unregister. Take led_cdev->led_access, set LED_SYSFS_DISABLE, perform the
trigger, timer, brightness, and trigger-sysfs teardown, then release the
mutex. A racing sysfs writer either completes before unregister starts or
sees the disabled state and returns -EBUSY instead of touching an object that
the driver may free.
Fixes: e381322b0190 ("leds: Introduce userspace LED class driver")
Cc: stable@vger.kernel.org
Signed-off-by: David Lee <david.lee@trailofbits.com>
Assisted-by: Codex:gpt-5.5
---
Trail of Bits has a minimal PoC that triggers this crash on a custom
kernel build, which can be shared further if needed.
drivers/leds/led-class.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index a51b0ed53886..a697d6740011 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -616,6 +616,9 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
if (IS_ERR_OR_NULL(led_cdev->dev))
return;
+ mutex_lock(&led_cdev->led_access);
+ led_sysfs_disable(led_cdev);
+
#ifdef CONFIG_LEDS_TRIGGERS
down_write(&led_cdev->trigger_lock);
if (led_cdev->trigger)
@@ -636,6 +639,8 @@ void led_classdev_unregister(struct led_classdev *led_cdev)
if (led_cdev->flags & LED_BRIGHT_HW_CHANGED)
led_remove_brightness_hw_changed(led_cdev);
+ mutex_unlock(&led_cdev->led_access);
+
device_unregister(led_cdev->dev);
down_write(&leds_list_lock);
next reply other threads:[~2026-07-09 10:12 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-09 10:12 David Lee [this message]
2026-07-09 10:30 ` [PATCH] leds: class: disable sysfs before unregistering LED devices sashiko-bot
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=20260709101210.104975-1-david.lee@trailofbits.com \
--to=david.lee@trailofbits.com \
--cc=dominik.czarnota@trailofbits.com \
--cc=lee@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-leds@vger.kernel.org \
--cc=pavel@kernel.org \
--cc=stable@vger.kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.