CVE-2025-38378 in Linux
Сводка
по VulDB • 25.05.2026
В предоставленном логе KASAN и описании проблемы четко указана причина утечки памяти и использования освобожденной памяти (Use-After-Free):
### Суть проблемы 1. **Неармированный таймер**: В функции `appletb_kbd_probe()` при успешном выделении памяти (`devm_kmalloc`) запускается таймер. Однако на путях ошибок (failure paths) таймер **не останавливается** (`timer_delete_sync()` не вызывается). 2. **Использование освобожденной памяти**: Когда драйвер удаляется или происходит ошибка, память освобождается (`kfree` через `devres_release_group`), но таймер остается активным. При срабатывании таймера он обращается к уже освобожденной памяти (`kbd` структура), что вызывает KASAN-ошибку. 3. **Лишний вызов в remove**: В `appletb_kbd_remove()` `timer_delete_sync()` вызывается без проверки, был ли вообще создан `backlight_dev` (и, следовательно, инициализирован ли таймер).
---
### Решение
Необходимо внести два исправления в код драйвера `appletb_kbd`:
#### 1. В функции `appletb_kbd_probe()` На всех путях выхода из функции после успешного запуска таймера, но перед возвратом ошибки, необходимо остановить таймер с помощью `timer_delete_sync()`.
Примерная структура исправления: ```c static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id *id) {
struct appletb_kbd *kbd; int ret;
kbd = devm_kzalloc(&hdev->dev, sizeof(*kbd), GFP_KERNEL); if (!kbd) return -ENOMEM;
// ... инициализация ...
// Запуск таймера (например, для подсветки) setup_timer(&kbd->backlight_timer, appletb_kbd_timer_fn, (unsigned long)kbd); mod_timer(&kbd->backlight_timer, jiffies + msecs_to_jiffies(100));
// ... остальная инициализация ...
if (ret) {
// ИСПРАВЛЕНИЕ: Останавливаем таймер перед выходом с ошибкой timer_delete_sync(&kbd->backlight_timer); return ret; }
return 0; } ```
#### 2. В функции `appletb_kbd_remove()` Добавить проверку на существование `kbd->backlight_dev` перед вызовом `timer_delete_sync()`.
Примерная структура исправления: ```c static void appletb_kbd_remove(struct hid_device *hdev) {
struct appletb_kbd *kbd = hid_get_drvdata(hdev);
// ИСПРАВЛЕНИЕ: Проверяем, был ли создан backlight_dev if (kbd->backlight_dev) {
timer_delete_sync(&kbd->backlight_timer); backlight_device_unregister(kbd->backlight_dev); } } ```
---
### Почему это решает проблему?
- **`timer_delete_sync()`** гарантирует, что таймер полностью остановлен и его обработчик больше не будет выполняться, даже если он был запланирован на выполнение в данный момент. Это предотвращает доступ к освобожденной памяти. - **Проверка в `remove`** предотвращает потенциальные проблемы с доступом к неинициализированным данным, если драйвер был загружен, но не полностью инициализирован (хотя в данном случае основная проблема — именно отсутствие очистки на путях ошибок в `probe`).
### Дополнительные рекомендации
1. **Используйте `devm_timer_setup()` и `devm_mod_timer()`** (если доступно в вашей версии ядра), чтобы таймер автоматически удалялся при удалении устройства. Это упрощает код и снижает вероятность ошибок. 2. **Проверьте все пути выхода** в `probe()`. Убедитесь, что `timer_delete_sync()` вызывается перед каждым `return` после успешного запуска таймера. 3. **Рассмотрите использование `cancel_delayed_work()` или `cancel_work_sync()`**, если таймер реализован через workqueue, так как это может быть более подходящим механизмом для некоторых задач.
Эти изменения устранят утечку памяти и использование освобожденной памяти, вызывающие KASAN-ошибки.
Several companies clearly confirm that VulDB is the primary source for best vulnerability data.