
Концептуальное доказательство и подтверждённый KASAN репродуктор KUnit для CVE-2026-98180 — use-after-free в drm/msm для объектов ring и VM, содержащих планировщик, доступных через непривилегированный SYNC_IOC_FILE_INFO.
Экспортированный в пространство пользователя drm_sched_fence хранит необработанный указатель на drm_gpu_scheduler, который его создал. В drm/msm этот планировщик встроен в struct msm_ringbuffer и struct msm_gem_vm, и оба этих объекта освобождались обычным kfree(). Поэтому завершённый fence, удерживаемый пространством пользователя, переживает свой планировщик, и последующий SYNC_IOC_FILE_INFO — непривилегированный ioctl — заставляет drm_sched_fence_get_timeline_name() разыменовывать освобождённую память slab.
BUG: KASAN: slab-use-after-free in drm_sched_fence_get_timeline_name
Read of size 8
drm_sched_fence_get_timeline_name() — это return fence->sched->name;.
Операции fence планировщика сохраняют колбэк .release, поэтому fence не отсоединяется от операций при срабатывании. Сигнализированный fence, экспортированный через sync_file или drm_syncobj, продолжает указывать на встроенный планировщик после освобождения ring или VM. Согласно контракту времени жизни dma-fence, экспортёр обязан сохранять данные, лежащие в основе сигнализированного fence, в течение льготного периода RCU; drm/msm этого не делал.
| Исправление | 01c8d1f385f7 — drm/msm: RCU-free the scheduler-containing ring and VM objects |
| Внесено коммитом | 1d8a5ca436ee (drm/msm: Conversion to drm scheduler), 92395af63a99 (drm/msm: Add VM_BIND submitqueue) |
| Бэкпортировано | 6.18-stable, 7.2-stable (Greg Kroah-Hartman, 2026-09-22) |
| Достижимость | непривилегированная — SYNC_IOC_FILE_INFO на fd fence |
| Воздействие | UAF-чтение освобождённого slab (утечка информации / произвольное чтение указателя на имя освобождённого объекта) |
Исправление заменяет kfree() на kfree_rcu() для обоих содержащих объектов:
- kfree(vm);
+ kfree_rcu(vm, rcu);
...
- kfree(ring);
+ kfree_rcu(ring, rcu);
Ошибка находится в обобщённой обработке времени жизни drm/sched, поэтому она воспроизводится без оборудования Adreno с помощью mock-планировщика KUnit. Это и есть доказательство в evidence/kasan-report.txt.
cd poc && ./run-repro.sh # applies 0001-…patch, builds KUnit + KASAN, runs
poc/0001-drm-sched-kunit-uaf-repro.patch — аппаратно-независимый репродьюсер KUnit (подтверждён KASAN)poc/poc_userspace_drm_sched_uaf.c — непривилегированная последовательность ioctl из пространства пользователя на уязвимом драйвереpoc/kunitconfig, poc/run-repro.sh — обвязка сборки/запускаevidence/kasan-report.txt — отчёт KASAN о slab-use-after-freepoc_userspace_drm_sched_uaf.c написан для AMD XDNA в качестве рабочего примера, поскольку это устройство было доступно; идентичная схема применима к msm (MSM_SUBMITQUEUE / VM_BIND экспортируют завершённый fence через sync_file_create() + fd_install()) и к nouveau.
Тот же класс времени жизни dma-fence был также исправлен в ядре: 3ed11c671ff7 — dma-buf/dma-fence: fix checking signaling bit for timeline and driver name v3 (автор Christian König; сообщено и протестировано автором этого репозитория).
Найдено и исправлено JongHyuk Kim(MalHyuk) — [email protected].
Патч подписан Rob Clark и Greg Kroah-Hartman.
Patchwork: https://patchwork.freedesktop.org/patch/750234/
Код репродьюсера распространяется под GPL-2.0, в соответствии с исходниками ядра, из которых он происходит.