Поиск уязвимостей в CUDA: новый подход к фаззингу на GPU

Автор: Денис Аветисян


В статье рассматривается инновационный конвейер фаззинга, использующий динамическую бинарную инструментацию и контекстно-зависимый анализ для выявления ошибок памяти в CUDA-программах.

🚀 Квантовые новости

Подключайся к потоку квантовых мемов, теорий и откровений из параллельной вселенной.
Только сингулярные инсайты — никакой скуки.

Присоединиться к каналу
По мере распространения гетерогенных систем закономерно увеличивается и количество уязвимостей, которые в них можно эксплуатировать.
По мере распространения гетерогенных систем закономерно увеличивается и количество уязвимостей, которые в них можно эксплуатировать.

Исследование посвящено решению проблем безопасности гетерогенных систем посредством GPU-ориентированного фаззинга и применению Address Sanitization.

Современные вычислительные системы всё чаще используют гетерогенные архитектуры с тесным взаимодействием CPU и GPU, однако безопасность GPU-программного обеспечения значительно отстает от CPU. В работе «Challenges and Design Considerations for Finding CUDA Bugs Through GPU-Native Fuzzing» исследуются ключевые проблемы обеспечения безопасности памяти в таких системах и демонстрируется неэффективность существующих методов, основанных на эмуляции GPU-кода на CPU. Предлагается новый подход к поиску уязвимостей в CUDA-программах, основанный на GPU-нативном фаззинге с использованием динамической бинарной инструментации и контекстно-зависимого анализа. Сможет ли предложенный метод существенно повысить надежность и безопасность гетерогенных вычислительных систем, активно используемых в современных научных и AI-приложениях?


Гетерогенные системы: растущая пропасть в безопасности

Современные вычислительные системы всё чаще используют гетерогенные архитектуры, объединяющие центральные процессоры (CPU) и графические процессоры (GPU) для значительного ускорения обработки данных. Эта тенденция обусловлена растущими потребностями в производительности, особенно в таких областях, как машинное обучение, научные вычисления и обработка больших данных. Вместо того, чтобы полагаться исключительно на CPU, которые традиционно отвечали за все вычислительные задачи, современные системы распределяют нагрузку между CPU и GPU, используя сильные стороны каждого из них. GPU, изначально разработанные для обработки графики, оказались исключительно эффективными в выполнении параллельных вычислений, что делает их идеальными для ускорения широкого спектра задач. В результате, гетерогенные системы становятся стандартом де-факто в высокопроизводительных вычислениях, открывая новые возможности для инноваций и решения сложных проблем.

Современные вычислительные системы все чаще используют гетерогенные архитектуры, объединяющие центральные и графические процессоры. Однако, в то время как безопасность центральных процессоров подвергается тщательному анализу и совершенствованию на протяжении десятилетий, графические процессоры часто отстают в плане всестороннего тестирования и разработки мер защиты. Эта разница обусловлена как историческими причинами — графические процессоры изначально проектировались для визуализации, а не для выполнения критически важных вычислений, — так и сложностью архитектуры графических процессоров, которая затрудняет обнаружение и устранение уязвимостей. В результате, гетерогенные системы могут содержать слабые места, которые злоумышленники способны использовать для компрометации данных или нарушения работы всей системы, что требует повышенного внимания к безопасности графических ускорителей.

Особую опасность уязвимости в гетерогенных системах представляют рабочие нагрузки машинного обучения. Эти приложения, критически зависящие от графических процессоров для ускорения вычислений, обрабатывают огромные объемы конфиденциальных данных, таких как персональная информация и финансовые отчеты. В связи с тем, что безопасность графических процессоров зачастую отстает от центральных процессоров, злоумышленники могут использовать эти уязвимости для компрометации данных или нарушения работы критически важных алгоритмов. Повышенная сложность архитектуры графических процессоров и недостаток специализированных инструментов тестирования безопасности усугубляют ситуацию, делая защиту машинного обучения от атак особенно сложной задачей.

GPU-Native Fuzzing: новый подход к тестированию

Предлагаемая схема GPU-Native Fuzzing предназначена для непосредственного тестирования программ для GPU на аппаратном обеспечении GPU, что позволяет преодолеть ограничения, присущие традиционному CPU-based fuzzing. В отличие от подходов, эмулирующих выполнение GPU на CPU, данная схема выполняет тестирование непосредственно на целевом оборудовании, обеспечивая более точную и эффективную проверку. Это позволяет выявлять ошибки, специфичные для архитектуры GPU и связанные с особенностями параллельного выполнения, которые могут быть не обнаружены при эмуляции. Такой подход особенно важен для тестирования сложных GPU-приложений, таких как драйверы, шейдеры и алгоритмы машинного обучения, где производительность и корректность имеют первостепенное значение.

В основе предложенного конвейера фаззинга лежит динамическая бинарная инструментация (DBI), позволяющая анализировать и изменять исполнение программы непосредственно во время работы. DBI предоставляет возможность перехвата и модификации инструкций, регистров и памяти, что необходимо для внедрения фаззинговых мутаций и отслеживания поведения программы. Благодаря этому, конвейер способен генерировать и внедрять тестовые примеры, ориентированные на конкретные участки кода и типы данных, а также отслеживать влияние этих изменений на выполнение программы в реальном времени. Использование DBI позволяет обойти ограничения, связанные с отсутствием информации о внутреннем устройстве GPU и сложностью отладки GPU-кода, обеспечивая эффективную генерацию целевых тестовых случаев.

Эффективность предложенного подхода к фаззингу напрямую зависит от интеграции контекстно-зависимого фаззинга и мутаций с учетом типов данных. Контекстно-зависимый фаззинг позволяет учитывать текущее состояние программы и путь выполнения при генерации тестовых примеров, что повышает вероятность обнаружения ошибок в сложных сценариях. Мутации с учетом типов данных обеспечивают создание валидных входных данных, соответствующих ожидаемым типам переменных и структур данных, используемых в GPU-программе. Это существенно снижает количество невалидных входных данных, которые могут привести к преждевременному завершению программы или непредсказуемым результатам, и позволяет глубже исследовать пространство возможных входных данных для выявления уязвимостей.

Надёжное обнаружение ошибок: обеспечение безопасности памяти

В рамках нашей системы обнаружения ошибок, Address Sanitization является ключевым компонентом, обеспечивающим динамическое выявление ошибок памяти во время выполнения GPU-программ. Данный механизм позволяет обнаруживать такие распространенные уязвимости, как переполнение буфера (buffer overflows) и использование памяти после освобождения (use-after-frees). Обнаружение осуществляется во время выполнения программы, что позволяет выявлять ошибки, которые не могут быть обнаружены статическим анализом кода. В случае обнаружения ошибки, Address Sanitization немедленно останавливает выполнение программы и предоставляет подробную информацию о причине и месте возникновения ошибки, что значительно упрощает процесс отладки и исправления.

Для повышения эффективности обнаружения ошибок в процессе фаззинга используется отслеживание покрытия кода (Coverage Tracking). Данная технология позволяет динамически анализировать, какие участки кода были выполнены в ходе тестирования, и направлять фаззер на исследование ранее не пройденных путей выполнения. Это достигается путем регистрации информации о выполненных инструкциях и ветвлениях, что позволяет оптимизировать генерацию тестовых данных и увеличивать вероятность обнаружения ошибок, особенно в сложных и малоиспользуемых частях кода. Отслеживание покрытия существенно расширяет область тестирования, выходя за рамки простого случайного ввода, и обеспечивает более полное и целенаправленное исследование кода на предмет уязвимостей.

Инструмент NVIDIA NVBit является базовой платформой для реализации как Address Sanitization, так и Coverage Tracking в рамках GPU-Native Fuzzing Pipeline. NVBit предоставляет низкоуровневые механизмы для инструментирования GPU-кода, позволяя отслеживать доступ к памяти и выполнять сбор информации о покрытии кода. Это позволяет динамически выявлять ошибки, связанные с некорректным использованием памяти (например, переполнение буфера, использование после освобождения), а также направлять процесс фаззинга по ранее неисследованным путям выполнения, существенно повышая эффективность обнаружения ошибок в GPU-приложениях.

CUDA и за её пределами: влияние на безопасность GPU

Разработанный конвейер фаззинга, ориентированный на GPU, обеспечивает бесшовную интеграцию с CUDA — доминирующей платформой для параллельных вычислений на графических процессорах. Эта совместимость позволяет эффективно анализировать и тестировать код, написанный для CUDA, непосредственно на аппаратном обеспечении GPU. Конвейер спроектирован таким образом, чтобы использовать преимущества архитектуры GPU для ускорения процесса фаззинга, генерируя и выполняя большое количество тестовых случаев с целью выявления уязвимостей и ошибок в программном обеспечении. Благодаря поддержке CUDA, система способна обрабатывать сложные параллельные программы, распространенные в таких областях, как машинное обучение, научные вычисления и обработка изображений, предоставляя надёжный инструмент для обеспечения безопасности и надёжности GPU-приложений.

Понимание взаимосвязи между PTX — промежуточным представлением CUDA — и SASS, машинным кодом GPU, является критически важным для эффективного фаззинга и анализа ошибок. PTX служит платформонезависимым языком, позволяющим разработчикам оптимизировать код для различных архитектур GPU. Однако, именно SASS, исполняемый непосредственно на GPU, определяет поведение программы и потенциальные уязвимости. Эффективный фаззинг требует анализа как PTX, для понимания логики программы, так и SASS, для выявления ошибок, возникающих при аппаратной реализации. Исследование трансформации PTX в SASS позволяет более точно генерировать тестовые примеры, направленные на конкретные участки кода и потенциальные уязвимости, что значительно повышает эффективность обнаружения ошибок в сложных GPU-программах.

Предварительные эксперименты с 11 библиотеками cuBLAS показали, что существующие образцы кода CUDA демонстрируют относительно низкое покрытие кода, со средним геометрическим значением в 25.98%. Это указывает на значительный пробел в исследовании состояний сложных GPU-программ. Максимальное покрытие, достигнутое в ходе тестирования, составило 64.29% для библиотеки ‘asum’, в то время как минимальное — всего 9.09% для библиотеки ‘rotm’. Полученные результаты подчёркивают необходимость в более эффективных методах тестирования и анализа безопасности CUDA-приложений, способных обеспечить более полное исследование их функциональности и выявление потенциальных уязвимостей.

Исследование, посвящённое поиску ошибок в CUDA-программах с использованием GPU-нативного фаззинга, закономерно выявляет сложности, связанные с обеспечением безопасности в гетерогенных системах. Авторы предлагают конвейер, использующий динамическую бинарную инструментацию и контекстно-зависимый фаззинг. Всё это, конечно, прекрасно, но стоит помнить, что продакшен всегда найдёт способ обойти даже самую элегантную теорию. Как говорил Г.Х. Харди: «Математика — это наука о том, что невозможно, а всё остальное — не математика». Здесь та же история: стремясь к идеальному обнаружению ошибок, исследователи сталкиваются с суровой реальностью — реальные программы всегда будут сложнее, а баги — изобретательнее.

Что дальше?

Предложенные методы GPU-ориентированного фаззинга, безусловно, являются шагом вперёд в обнаружении ошибок памяти в CUDA программах. Однако, как показывает опыт, каждое найденное уязвимое место порождает дюжину новых, просто более тщательно замаскированных. Уверенность в том, что динамическая бинарная инструментация действительно охватывает все возможные пути исполнения на современных графических процессорах, наивна. Оптимизации компилятора, которые считаются благом, зачастую становятся соучастниками уязвимостей, стирая границы между логикой программы и ошибками реализации.

Очевидным направлением является углубление контекстно-зависимого фаззинга. Но стоит помнить, что увеличение контекста неминуемо приводит к экспоненциальному росту вычислительных затрат. В конечном итоге, алгоритмы, элегантно работающие на тестовых примерах, столкнутся с реальными, сложными приложениями, где производительность станет критическим фактором. Не исключено, что мы просто переложим проблему с обнаружения ошибок на проблему масштабируемости фаззинга.

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


Оригинал статьи: https://arxiv.org/pdf/2603.05725.pdf

Связаться с автором: https://www.linkedin.com/in/avetisyan/

Смотрите также:

2026-03-09 19:57