summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorVicki Pfau <vi@endrift.com>2026-03-09 21:50:34 -0700
committerHans Verkuil <hverkuil+cisco@kernel.org>2026-03-16 16:30:20 +0100
commit323f52e02be68889c8630c4a0415ef5b78f9dc63 (patch)
tree1247036a28b3fc0bb40bb30fdc7d47e45f011dd8 /drivers/media
parent68380ec2161ee61ce4f23001dfb536bbaa8f4979 (diff)
downloadlwn-323f52e02be68889c8630c4a0415ef5b78f9dc63.tar.gz
lwn-323f52e02be68889c8630c4a0415ef5b78f9dc63.zip
media: pulse8-cec: Handle partial deinit
In the event that the cec dev node is held open while the adapter is disconnected the serio device will be cleaned up but the cec device won't be. As the serio device is freed but the ping_eeprom_work is not canceled, the next ping will still attempt to send, leading to a kernel oops. This patch both cancels the ping_eeprom_work in the serio cleanup as well as checking to make sure the serio is still present before attempting to write to it. Note that while the added serio = NULL line looks similar to one that was removed in commit 024e01dead12c ("media: pulse8-cec: fix duplicate free at disconnect or probe error"), it notably happens before calling cec_unregister_adapter, and as such shouldn't lead to the user-after-free that removing it fixed. Signed-off-by: Vicki Pfau <vi@endrift.com> Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/cec/usb/pulse8/pulse8-cec.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/media/cec/usb/pulse8/pulse8-cec.c b/drivers/media/cec/usb/pulse8/pulse8-cec.c
index 0df3af152762..fa5df1062753 100644
--- a/drivers/media/cec/usb/pulse8/pulse8-cec.c
+++ b/drivers/media/cec/usb/pulse8/pulse8-cec.c
@@ -235,6 +235,9 @@ static int pulse8_send_and_wait_once(struct pulse8 *pulse8,
{
int err;
+ if (!pulse8->serio)
+ return -ENODEV;
+
if (debug > 1)
dev_info(pulse8->dev, "transmit %s: %*ph\n",
pulse8_msgname(cmd[0]), cmd_len, cmd);
@@ -655,6 +658,10 @@ static void pulse8_disconnect(struct serio *serio)
{
struct pulse8 *pulse8 = serio_get_drvdata(serio);
+ cancel_delayed_work_sync(&pulse8->ping_eeprom_work);
+ mutex_lock(&pulse8->lock);
+ pulse8->serio = NULL;
+ mutex_unlock(&pulse8->lock);
cec_unregister_adapter(pulse8->adap);
serio_set_drvdata(serio, NULL);
serio_close(serio);