[lvc-project] [PATCH] media: rc: Fix use-after-free when racing vfd_write() with disconnect
Sergey Larshin
Sergey.Larshin at kaspersky.com
Thu Jul 24 19:15:47 MSK 2025
> Жизненный цикл ictx контролируется с помощью счётчика ссылок &ictx->users.
> Если счётчик в imon_disconnect() становится равным нулю после декремента,
> то объект освобождается.
Cпасибо за материалы, изучив логику ictx->users, пришёл к выводу, что проблема не во
всём ctx — он защищён корректно. Однако два его поля — usbdev_intf0 и
usbdev_intf1 — не защищены. При disconnect() они уменьшается счётчик
ссылок на устройство в зависимости от номера интерфейса.
В imon_probe в зависимости от номера интерфейса вызываются функции
imon_init_intf0 или imon_init_intf1, каждая из которых увеличивает
счётчик ссылок на usb_device на один.
В imon_disconnect счётчик уменьшается на один, независимо от
ictx->users, что приводит к освобождению usbdev_intf0 или
usbdev_intf1 через вызов usb_put_dev(). В то время как vfd_write
продолжает работу.
Решений может быть несколько:
- Делать usb_put_dev, когда отчищаем icxt (падение не воспроизвелось
в течении 40 минут)
if (refcount_dec_and_test(&ictx->users)) {
if (ictx->usbdev_intf0)
usb_put_dev(ictx->usbdev_intf0);
if (ictx->usbdev_intf1)
usb_put_dev(ictx->usbdev_intf1);
free_imon_context(ictx);
}
- Сделать lock в disconnect()
При этом ранее описанные доводы о необходимости атомарного доступа
к флагу disconnected остаются актуальными, и предложенный патч
корректно решает данную проблему.
Thread 1 vfd_write Thread 2 imon_disconnect
...
if
usb_put_dev(ictx->usbdev_intf0)
else
usb_put_dev(ictx->usbdev_intf1)
...
while
send_packet
if
pipe = usb_sndintpipe(
ictx->usbdev_intf0) UAF
else
pipe = usb_sndctrlpipe(
ictx->usbdev_intf0, 0); UAF
More information about the lvc-project
mailing list