# Several Linux kernel vulnerabilities accidentally posted to public mailing list

> AI Release · @ai_release1 · https://ai-release.org/guides/several-linux-kernel-vulnerabilities-accidentally-poste.html

## TL;DR
- Время выполнения: 40–60 минут (без учёта перезагрузки и окна обслуживания)
- Уровень сложности: Intermediate
- Понадобится: Linux-хост с sudo, `git`, `curl`, `jq`, `python3`, пакетный менеджер `apt` или `dnf`, публичный архив рассылки ядра (lore.kernel.org), 2 ГБ свободного места, снапшот или резервная копия ВМ

Сценарий, под который написан гайд: патчи безопасности ядра попали в публичную рассылку раньше официального анонса. Для администратора это означает, что детали уязвимости уже видны снаружи, а готового пакета с исправлением может ещё не быть. Задача — быстро понять, какие подсистемы затронуты, и закрыть риск до выхода обновления.

## Требования и подготовка
![Иллюстрация к разделу «Требования и подготовка»](https://ai-release.org/guides/img/several-linux-kernel-vulnerabilities-accidentally-poste-ru-1.jpg?v=1792778660)

- ОС: Linux с systemd, дистрибутив и версию ядра фиксируем командами ниже (конкретные номера версий сверьте с документацией вашего дистрибутива — в гайде их нет намеренно).
- Права: `sudo` или root.
- Пакеты: `git`, `curl`, `jq`, `python3`, `lscpu`, `pciutils` (`lspci`), `kmod` (`lsmod`, `modprobe`).
- Доступ: исходящий HTTPS к архиву рассылки и к git-зеркалу ядра (адреса зеркал сверьте с текущей документацией kernel.org).
- Место: не менее 2 ГБ под клон стабильного дерева.
- Процедура: согласуйте окно перезагрузки. Ядро — компонент, который нельзя обновить «на горячую» без livepatch.

Проверьте базу:

```bash
uname -r
cat /etc/os-release | head -n 3
df -h / | tail -n 1
```

**Пример вывода:**

```
6.x.y-<сборка-дистрибутива>
NAME="<Дистрибутив>"
VERSION="<версия>"
/dev/sda2        50G   18G   30G  38% /
```

Почему это работает: `uname -r` берёт строку версии из работающего ядра, а `cat /etc/os-release` — из пользовательского пространства. Если они расходятся с тем, что вы видите в трекере уязвимостей, значит вы патчите не тот хост.

Если тестовое окружение у вас на Android-терминале, порядок проверки митигаций описан в [гайде по Termux и PRoot](https://ai-release.org/guides/kak-zapustit-linux-na-android-bez-root-termux-proot-i-i.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide). Если ядро используется в WSL, обновление приходит вместе с обновлением Windows — см. [WSL 3.0: что нового и как обновить](https://ai-release.org/guides/wsl-3-0-windows.html?utm_source=tg&utm_medium=channel&utm_campaign=guide_inline&utm_content=guide_to_guide).

Чек-лист подготовки:

- [ ] Зафиксирована версия ядра и дистрибутив
- [ ] Есть снапшот ВМ или резервная копия
- [ ] Согласовано окно перезагрузки
- [ ] Проверены права `sudo`
- [ ] Свободно ≥ 2 ГБ на диске

## Шаг 1. Инвентаризация: версия ядра и активные митигации

**Что сделать:** снять «слепок» хоста — версию ядра, параметры загрузки, состояние модулей и таблицу уже включённых митигаций (mitigation — обходной механизм в ядре, снижающий эксплуатируемость уязвимости без исправления кода).

**Зачем:** без базовой линии вы не отличите «стало лучше после патча» от «так было всегда». Митигации в `/sys/devices/system/cpu/vulnerabilities/` — это интерфейс ядра, где по одному файлу на класс атак записан текущий статус.

**Как проверить:** команды ниже должны завершиться без ошибок, а файл инвентаризации — содержать непустые строки.

```bash
sudo -v
{
  echo "host=$(hostname)"
  echo "kernel=$(uname -r)"
  echo "cmdline=$(cat /proc/cmdline)"
  grep -H . /sys/devices/system/cpu/vulnerabilities/* 2>/dev/null
  lsmod | awk 'NR>1 {print $1}'
} > kernel-inventory-$(date +%F).txt
wc -l kernel-inventory-$(date +%F).txt
```

**Пример вывода:**

```
host=web-01
kernel=6.x.y-<сборка-дистрибутива>
cmdline=BOOT_IMAGE=/vmlinuz root=/dev/sda2 ro quiet
/sys/devices/system/cpu/vulnerabilities/<имя-файла>: Mitigation: <описание>
...
128 kernel-inventory-2025-01-01.txt
```

Отдельно проверьте, не отключены ли митигации вручную — это частая причина «у нас всё было защищено, а после миграции нет»:

```bash
cat /proc/cmdline | tr ' ' '\n' | grep -E 'mitigations|nopti|nospectre'
```

Если в выводе есть `mitigations=off` — запишите это как отдельный риск. Почему это работает: параметры из `/proc/cmdline` — это фактическая командная строка текущего ядра, а не то, что записано в конфиге загрузчика.

## Шаг 2. Сопоставить публично раскрытые изменения со своим железом
![Иллюстрация к разделу «Шаг 2. Сопоставить публично раскрытые изменения со своим железом»](https://ai-release.org/guides/img/several-linux-kernel-vulnerabilities-accidentally-poste-ru-2.jpg?v=1792778672)

**Что сделать:** найти коммиты, попавшие в публичную рассылку, определить затронутую подсистему и проверить, используется ли она на хосте.

**Зачем:** уязвимость в ядре эксплуатируема только если соответствующий код присутствует и доступен. Драйвер несуществующего устройства или отключённый модуль — это снижение приоритета, а не «всё срочно».

**Как проверить:** `git log` показывает коммиты, а `lsmod`/`lspci` подтверждают (или опровергают) наличие подсистемы на конкретной машине.

```bash
git clone --depth 200 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git ~/linux-stable
cd ~/linux-stable
git log --oneline -n 20 --grep="CVE"
```

**Пример вывода:**

```
a1b2c3d <подсистема>: fix <краткое описание> (CVE-ГОД-НОМЕР)
...
```

Номера CVE (CVE — публичный идентификатор уязвимости вида CVE-ГОД-НОМЕР) и точные заголовки берите из самого коммита, не из пересказов. Если `git log --grep` ничего не находит, сверьтесь с документацией дерева: возможно, вы клонировали не ту ветку.

Дальше — триаж. Заполните таблицу под свой хост:

| Признак в коммите | Что проверить на хосте | Команда |
|---|---|---|
| Имя модуля ядра | Загружен ли модуль | `lsmod \| grep -i <имя-модуля>` |
| Сетевая подсистема | Слушает ли сервис наружу | `ss -tulpn` |
| Файловая система | Смонтирована ли ФС | `mount \| grep <фс>` |
| Драйвер устройства | Есть ли устройство | `lspci -k \| grep -i <вендор>` |

**Пример:** коммит правит модуль `nf_tables`. Проверяем:

```bash
lsmod | grep -i nf_tables
```

Вывод с непустой строкой означает, что код на хосте активен — приоритет высокий. Пустой вывод — код не загружен, но может подгрузиться по требованию; тогда смотрите, есть ли у непривилегированных пользователей доступ к сетевому стеку (контейнеры, user namespaces).

Варианты снижения риска до выхода пакета:

```bash
# 1) Выгрузить ненужный модуль и запретить автозагрузку
sudo modprobe -r <имя-модуля>
echo "blacklist <имя-модуля>" | sudo tee /etc/modprobe.d/blacklist-<имя-модуля>.conf

# 2) Ограничить поверхность атаки через sysctl
sudo sysctl -w kernel.unprivileged_bpf_disabled=1
sudo sysctl -w kernel.kptr_restrict=2

# 3) Проверить, есть ли уже livepatch (livepatch — подмена функций ядра без перезагрузки)
ls /sys/kernel/livepatch/ 2>/dev/null && cat /sys/kernel/livepatch/*/enabled 2>/dev/null
```

Почему это работает: `modprobe -r` выгружает код из памяти, а файл в `/etc/modprobe.d/` предотвращает его повторную автозагрузку. `sysctl`-переключатели сужают доступ непривилегированных процессов к подсистемам, которые чаще всего фигурируют в эксплойтах ядра. Настройки `sysctl` не постоянны — для сохранения после перезагрузки добавьте их в `/etc/sysctl.d/99-hardening.conf`, формат файла сверьте с документацией дистрибутива.

## Шаг 3. Проверка работы и финальный результат
![Иллюстрация к разделу «Шаг 3. Проверка работы и финальный результат»](https://ai-release.org/guides/img/several-linux-kernel-vulnerabilities-accidentally-poste-ru-3.jpg?v=1792778683)

**Что сделать:** установить обновление (или подтвердить, что митигация активна), перезагрузиться и доказать, что изменение применилось.

**Зачем:** пакет в кэше и пакет в работающем ядре — разные вещи. Пока не выполнена перезагрузка, `uname -r` показывает старое ядро.

**Как проверить:** сравнить `uname -r` до и после, посмотреть список установленных пакетов ядра и статус митигаций.

```bash
# Debian/Ubuntu
sudo apt update && sudo apt full-upgrade -y
sudo reboot

# RHEL/Fedora
sudo dnf updateinfo list security
sudo dnf upgrade --security -y
sudo reboot
```

После возврата хоста:

```bash
uname -r
sudo dpkg -l 'linux-image*' 2>/dev/null | grep ^ii | tail -n 3
grep . /sys/devices/system/cpu/vulnerabilities/* | grep -v "Not affected"
lsmod | grep -i <имя-модуля>; echo "exit=$?"
```

**Пример успешного вывода:**

```
6.x.y-<новая-сборка-дистрибутива>
ii  linux-image-<версия>  <арх>  Linux kernel image
/sys/devices/system/cpu/vulnerabilities/<имя-файла>: Mitigation: <описание>
exit=1
```

Что означает успех: строка `uname -r` отличается от значения в файле инвентаризации из Шага 1; в списке пакетов есть новый `linux-image-<версия>`; в выводе митигаций нет строки `Vulnerable`; `lsmod` не содержит проблемный модуль (`exit=1` — это нормальный результат, `grep` не нашёл совпадений).

## Возможные проблемы и решения

**Проблема. Обновление ядра не устанавливается, apt пишет про удержанные пакеты**
- Ошибка: `The following packages have been kept back: linux-image-generic`
- Причина: пакет удержан (`apt-mark hold`) или обновление идёт поэтапно (phased update) и до вашего хоста ещё не дошло.
- Решение: проверьте `apt-mark showhold`; если пакет в списке — `sudo apt-mark unhold linux-image-generic && sudo apt install linux-image-generic`. Если удержаний нет, установите явно: `sudo apt install --only-upgrade linux-image-generic`, а факт поэтапной выдачи сверьте с документацией дистрибутива.

**Проблема. Модуль не выгружается, митигация не применяется**
- Ошибка: `rmmod: ERROR: Module <имя-модуля> is in use`
- Причина: модуль удерживается другим модулем или активным сокетом/контейнером.
- Решение: найдите держателей `lsmod | grep -i <имя-модуля>` (столбец Used by), остановите зависимые сервисы `sudo systemctl stop <сервис>` и повторите `sudo modprobe -r <имя-модуля>`. Если выгрузить нельзя — оставьте модуль и закройте риск сетевым фильтром или livepatch до перезагрузки.

**Проблема. Файл митигации отсутствует**
- Ошибка: `grep: /sys/devices/system/cpu/vulnerabilities/<имя>: No such file or directory`
- Причина: работающее ядро старше, чем код, добавляющий этот интерфейс, либо митигация не применима к вашей архитектуре.
- Решение: сверьтесь с документацией по конкретному классу атак и обновите ядро; после перезагрузки повторите `grep . /sys/devices/system/cpu/vulnerabilities/*`. Не трактуйте отсутствие файла как «уязвимости нет».

## Резюме и следующие шаги

Вы получили воспроизводимый цикл: инвентаризация → сопоставление публично раскрытых коммитов со своим железом → митигация и проверка после перезагрузки. Дальше автоматизируйте Шаг 1 в cron или в системе управления конфигурациями, чтобы сравнивать слепки между хостами и замечать отключённые митигации до инцидента.

## FAQ

**Почему утечка в рассылку опаснее обычного CVE?**
Детали патча видны публично до выхода пакета, поэтому окно между «все знают» и «все обновились» больше. Отсюда приоритет на митигации из Шага 2.

**Можно ли обойтись без перезагрузки?**
Да, если для вашего ядра доступен livepatch: проверка — `ls /sys/kernel/livepatch/` и `cat /sys/kernel/livepatch/*/enabled`. Наличие и состав пакетов livepatch для вашего дистрибутива сверьте с документацией.

**Как быстро понять, затронут ли конкретный сервер?**
Сверьте загруженные модули (`lsmod`) и открытые порты (`ss -tulpn`) с подсистемой из коммита. Нет кода в памяти — нет эксплуатации этим путём, но остаётся автозагрузка модуля по требованию.

**Что делать, если патча ещё нет, а сервис критичный?**
Сузить поверхность атаки: выгрузить ненужные модули, применить `sysctl`-ограничения, закрыть сервис сетевым фильтром. Все действия фиксируйте, чтобы потом снять их после установки обновления.
