[lvc-project] [PATCH] media: rc: Fix use-after-free when racing vfd_write() with disconnect

Fedor Pchelkin pchelkin at ispras.ru
Wed Jul 23 18:43:46 MSK 2025


On Tue, 22. Jul 19:24, Larshin Sergey wrote:
> `imon_disconnect()` races with `vfd_write()`, `imon_disconnect()`

Наименования функций можно писать без кавычек. То что упоминается
функция, понятно по наличию скобок в конце. Количество `` можно
понизить.

> may complete the pending transfer and free `ictx`
> while `vfd_write()` is blocked in `wait_for_completion_interruptible()`.
> When `vfd_write()` wakes up, it accesses freed `ictx`,
> causing a use-after-free.
> 
> Thread 1 vfd_write()                       Thread 2 imon_disconnect()
> ...
> mutex_lock_interruptible(&ictx->lock)
> ...
> while
>   send_packet(ictx)
>     ictx->tx.busy = true // UAF
>     usb_submit_urb()
>     wait_for_completion_interruptible()
>     ...
>                                           ...
>                                           if (ictx->tx.busy)
>                                             usb_kill_urb(ictx->tx_urb)
>                                             complete(&ictx->tx.finished)
> 
>                                           ...
>                                           if (refcount_dec_and_test
>                                                          (&ictx->users))
>                                             free_imon_context(ictx)
> 
>     ictx->tx.busy = false // UAF

В https://syzkaller.appspot.com/bug?extid=f1a69784f6efe748c3bf UAF
происходит к struct usb_device.

Пока что из описания не ясно, в чём заключается проблема.

>     retval = ictx->tx.status
> 
> Set and read `ictx->disconnected` atomically.

Каким образом атомарность операций позволит что-то устранить при
наблюдаемой гонке?

> Acquire `ictx->lock` in `imon_disconnect()` after setting
> the flag to synchronize with writers holding the lock.
> This ensures writers exit safely before `disconnect()`
> proceeds with cleanup.

По регламентам работ требуется добавлять строчку

Found by Linux Verification Center (linuxtesting.org) with <tool>.

либо

Found by <organization> on behalf of Linux Verification Center (linuxtesting.org)
with <tool>.

https://portal.linuxtesting.ru/How-to-send-patches-to-kernel.html#Порядок-тегов

> 
> Reported-by: syzbot+f1a69784f6efe748c3bf at syzkaller.appspotmail.com
> Closes: https://syzkaller.appspot.com/bug?extid=f1a69784f6efe748c3bf
> Signed-off-by: Larshin Sergey <Sergey.Larshin at kaspersky.com>

Для патчей, устраняющих ошибки в ядре, желателен тег Fixes.
https://portal.linuxtesting.ru/How-to-send-patches-to-kernel.html#Fixes

> @@ -2499,7 +2507,11 @@ static void imon_disconnect(struct usb_interface *interface)
>  	int ifnum;
>  
>  	ictx = usb_get_intfdata(interface);
> -	ictx->disconnected = true;
> +	/* Ensure disconnect is visible to readers */
> +	smp_store_release(&ictx->disconnected, true);
> +	mutex_lock(&ictx->lock);
> +	mutex_unlock(&ictx->lock);

Ну это совсем уж dirty hack какой-то :)

Честно говоря, идея патча с использованием memory-ordering рутин
smp_load_acquire/smp_store_release для устранения гонки в драйвере не
понятна, т.к. параллельный поток, если он действительно параллельный,
может взять и изменить значение переменной сразу после её проверки

	/* Ensure we see device connect before proceeding */
	if (smp_load_acquire(&ictx->disconnected))
		return -ENODEV;

и полезность такой проверки становится равной нулю. А если секции чтения
и записи в ictx->disconnected обвешаны какими-нибудь локами, то зачем
нужен дополнительный smp_load_acquire()?

Возможно на что-то натолкнёт история этого драйвера, похожие гонки там уже
когда-то исправляли или пытались исправлять:

$ git log drivers/media/rc/imon.c

commit 24147897507cd3a7d63745d1518a638bf4132238
Author: Ricardo Ribalda <ribalda at chromium.org>
Date:   Mon May 6 21:10:27 2024 +0000

    media: imon: Fix race getting ictx->lock


commit 813ceef062b53d68f296aa3cb944b21a091fabdb
Author: Gautam Menghani <gautammenghani201 at gmail.com>
Date:   Wed Oct 19 06:02:14 2022 +0100

    media: imon: fix a race condition in send_packet()


commit db264d4c66c0fe007b5d19fd007707cd0697603d
Author: Tetsuo Handa <penguin-kernel at I-love.SAKURA.ne.jp>
Date:   Mon May 2 05:49:04 2022 +0200

    media: imon: reorganize serialization


> +
>  	dev = ictx->dev;
>  	ifnum = interface->cur_altsetting->desc.bInterfaceNumber;
>  
> @@ -2513,7 +2525,7 @@ static void imon_disconnect(struct usb_interface *interface)
>  	usb_set_intfdata(interface, NULL);
>  
>  	/* Abort ongoing write */
> -	if (ictx->tx.busy) {
> +	if (READ_ONCE(ictx->tx.busy)) {
>  		usb_kill_urb(ictx->tx_urb);
>  		complete(&ictx->tx.finished);
>  	}
> -- 
> 2.39.5



More information about the lvc-project mailing list