Разработка на скорости машин: как найти (и починить) уязвимость в Linux и Ginux

В Ginux первые исправления по моим отчётам попали в main за десять часов. Мой патч для Linux добрался до дерева Линуса за 69 дней. Между этими числами — два очень разных процесса разработки, в которых мне довелось поучаствовать: найти баг, воспроизвести, отправить мейнтейнеру.
Ginux: к утру уже починили
Недавно в новостях проскочил Ginux — эксперимент Грегори Курцера, сооснователя CentOS и создателя Rocky Linux. Идея: написать с нуля ядро на Rust с совместимостью с Linux, отдав основную работу агентам Codex. Получилось ядро x86-64 под UEFI, которое запускает отдельные немодифицированные программы из Linux-userspace в собственных «доменах». Файловые системы для них доставляются в OCI-образах.
Пройти мимо я не мог: Rust, Linux и агентная разработка в одном флаконе. В README написано, что G в названии официально от GPT, а неофициально ещё и от Greg. Ну а S в Ginux, как и в IoT, от Security.
Я прогнал проект через rust-in-peace и reproof. Сначала модель угроз, затем три независимых прохода поиска: вслепую, от модели угроз и от истории CVE. Каждый — четырьмя моделями (GLM 5.3, Kimi 3.1, Opus, Sonet). После — состязательная проверка, в которой агенты пытаются опровергнуть находки. Результаты воспроизвёл в QEMU.
Отчёты отправил через GitHub issues. На момент проверки в репозитории не было SECURITY.md и канала для приватных security advisories. Сам проект исследовательский: README прямо предупреждает об отсутствии независимого аудита и гарантий безопасности для production.
Примерно через четыре часа пришли ответы от агентов мейнтейнера и первые PR. Комментарии деловые: «Gate 21 fixes this in PR #36». Я даже не удержался от реплики написанной руками на рисовой бумаге: приятно смотреть, как агенты болтают между собой. К утру первые три исправления уже были в main.
Самая сочная находка — TLS-клиент реестра образов. Генератор случайных чисел инициализировался временем RTC, считанным при загрузке, с точностью до секунды. Для каждого соединения использовалось то же значение. В результате повторялись и client_random, и эфемерный ключ. Мы смогли расшифровать записанный TLS-трафик, включая данные приложения, по пассивному перехвату. Исправление влили примерно через 12 часов после отчёта.
К утру 2 ноября пять исправлений были в main, ещё десять PR ждали ревью. Можно рисовать себе бейдж за первые находки в Ginux.
Хронология Ginux, 2026 год. Время московское; интервалы — от первого issue, округлённо.
Когда | Что произошло | После первого отчёта |
|---|---|---|
31 октября — 1 ноября | Клон | — |
1 ноября, 17:05–18:58 | Отправлены 15 issues | Точка отсчёта |
1 ноября, 21:17–21:24 | 4 часа | |
2 ноября, 03:00 | Первые три исправления в | 10 часов |
2 ноября, 05:23 | Исправлен TLS RNG: PR #40 влит, issue закрыт | 12 часов |
2 ноября, 05:49 | Влит PR #42: проверка образа, закреплённого по digest | 13 часов |
2 ноября, 07:44 | Открыт последний из 15 PR; пять уже влиты, десять на ревью | 15 часов |
А теперь — та же работа в Linux.
Linux: четыре строки, два с половиной месяца
До Ginux я гонял RIP по ядру Linux. Отправил 16 находок по трём подсистемам: Android Binder, net/xfrm IP-TFS и nova-core. Для всех подготовил PoC, большинство проверил динамически в QEMU. До mainline к моменту этой статьи дошёл один патч — мой, для Rust-драйвера Binder.
Там массив файловых дескрипторов из транзакции разрастался во внутренние структуры, которым требовалось гораздо больше памяти, чем принято выдвать KVec. На 64-битной системе около 900 тысяч записей приводили к запросу 20,6 МиБ физически непрерывной памяти. Аллокатор страниц выдавал WARN. Следующему вектору требовалось ещё 13,7 МиБ, тоже непрерывных.
Физическая непрерывность этим структурам не нужна. Исправление заменяет KVec на KVVec для двух векторов, позволяя использовать vmalloc. Четыре изменённые строки.
Часть остальных отчётов мейнтейнеры по делу отклонили, часть проблем уже чинили параллельно, остальные ещё в работе. Детали неисправленного пока не раскрываю.
Хронология Linux, 2026 год. Интервалы — от отправки отчётов 17 августа.
Когда | Что произошло | После отчёта |
|---|---|---|
10–11 августа | Binder: три прохода × две модели, PoC в QEMU, повтор на C-драйвере — ARM64, конфиг Pixel 7 | — |
17 августа | Отправлены 16 находок по трём подсистемам | Точка отсчёта |
17 августа | Ответ мейнтейнера Binder: «Do you want to submit a patch?» | В течение суток |
25 августа | PATCH v1 в LKML | 8 дней |
28 августа | PATCH v2, | 11 дней |
17 сентября | Патч принят в | 31 день |
25 октября, МСК |
| 69 дней |
1 ноября, UTC / 2 ноября, 00:26 МСК | Вышел тег v7.4-rc1, включающий исправление | Около 76 дней |
Между v1 и v2, среди прочего, пришлось добавить забытый тег [PATCH] и убрать пайплайн из Suggested-by: rust-in-peace требует e-mail, а у пайплайна его нет. Благодарность агентам переехала в текст коммита.
Отдельно оставлю за скобками отправку патча через git send-email из Gmail (хорошо, что не через FIDO) и прочие технические мучения. Это уже мои проблемы: я не настоящий контрибьютор ядра, сбоку прибежал.
Что именно ускорилось
Linux | Ginux | |
|---|---|---|
Отправлено находок | 16 по трём подсистемам | 15 |
Канал | Письма мейнтейнерам, патч через LKML | GitHub issues |
Первая реакция | В течение суток, человек | Около 4 часов, агенты |
Кто готовил патч | Я, две итерации | Агенты мейнтейнера |
Исправление в основной ветке | 69 дней, дерево Линуса | Около 10 часов, |
Состояние к утру 2 ноября | Один патч в mainline и v7.4-rc1 | Пять исправлений в |
69 дней против десяти часов — примерно 160-кратный разрыв по календарю. Эти числа описывают путь отчёта до основной ветки. Они не измеряют скорость написания патча: в Linux ревью было уже на 11-й день, а затем патч проходил через дерево подсистемы и релизный цикл.
У Linux миллиарды устройств, обязательства по совместимости и цена регрессии. У Ginux — исследовательский прототип, автор которого прямо пишет, что для production он не годится. Прямое соревнование здесь было бы странным. Но разница в работе контрибтютера вполне осязаема.
Вот о чём я писал в «Манифесте созидателя»: патч, CI и ответ репортёру там уже стоят почти ноль. Человеческая работа смещается к проверке результата и решению о merge. Сам код почти ничего не стоит.
Гибсоновское «будущее уже здесь — оно просто неравномерно распределено» в этот раз можно наблюдать в двух репозиториях. Пока мои отчёты превращались в PR для Ginux, Линус выпускал v7.4-rc1 с моим патчем. Два бейджа за одни сутки.
А G, похоже, всё-таки от Greg: мой патч в Linux принимал один Грег, в Ginux — агенты другого.
Спасибо, Грегори, за отвагу, сожжённые токены и желание странного.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.