Баг прятался 18 лет: OpenAI нашла его в окне шириной в одну инструкцию
OpenAI рассказала, как нашла гонку потоков (race condition), которая 18 лет незаметно жила в GNU libunwind — одной из самых распространенных библиотек для раскрутки стека. Самое абсурдное в этом баге — ширина окна, в котором он срабатывает: буквально одна процессорная инструкция, порядка 100 пикосекунд. На таком масштабе казалось, что он слишком редкий, чтобы вообще проявляться. Но на нагрузке OpenAI это выливалось в больше десятка падений в день.
Все началось с "невозможных" крашей в Rockset — C++-инфраструктуре поиска, которую OpenAI купила в 2024 году и использует в ChatGPT для работы с данными и поиска по перепискам. Обычная функция завершалась и возвращалась не туда: иногда по нулевому адресу, иногда указатель стека оказывался смещен на 8 байт. Так нормальный код просто не падает. Для каждой гипотезы у инженеров находилось опровержение, и баг выглядел невозможным.
Перелом случился, когда команда сменила оптику. Сначала они отлаживали как врач: брали один кор-дамп и пытались поставить диагноз по детальным уликам. Это не работало. Тогда подход поменяли на эпидемиологический — смотреть не на отдельный случай, а на всю популяцию крашей. Скрипт, который скачал и разметил все дампы памяти Rockset за год, написал сам ChatGPT. На чистых данных корреляции проявились мгновенно: то, что считали одним багом, оказалось двумя независимыми. Первый — тихий аппаратный сбой: процессор на одном хосте Azure буквально неправильно считал. Второй — та самая гонка в libunwind.
Сам уязвимый код появился еще в 2007–2008 годах — в первой версии libunwind с поддержкой раскрутки C++-исключений для x86_64 — и все это время спокойно работал. Механизм libunwind можно описать просто. Механизм libunwind можно описать просто. Когда C++ обрабатывает
Читать на habr.com