]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
media: pulse8-cec: Handle partial deinit
authorVicki Pfau <vi@endrift.com>
Tue, 10 Mar 2026 04:50:34 +0000 (21:50 -0700)
committerHans Verkuil <hverkuil+cisco@kernel.org>
Mon, 16 Mar 2026 15:30:20 +0000 (16:30 +0100)
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>
drivers/media/cec/usb/pulse8/pulse8-cec.c

index 0df3af152762c526c9678e27d6600ca9f83a7a04..fa5df106275395cd26f681528427d8fb5cb03b49 100644 (file)
@@ -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);