Назад к блогу

Ошибки компиляции arm64 и уязвимости curl: что на самом деле известно

Ошибки компиляции arm64 и уязвимости curl: что на самом деле известно

Разбираем, действительно ли ошибки при кросс-компиляции curl под arm64 способны привести к появлению уязвимостей в собранном бинарнике. Сопоставляем официальные инструкции по сборке и таблицу CVE, чтобы отделить реальные факты от громких заявлений.

Разбираем вопрос, который звучит интригующе: будто ошибки компиляции под arm64 приводили к попаданию неверной логики в бинарник curl и это оборачивалось уязвимостями. Проверим, что об этом говорят сами инструкции по сборке curl и таблица CVE проекта, и где заканчиваются факты.

Как устроена сборка curl из исходников

Сборка описана как последовательность шагов: сначала настройка через ./configure с нужными опциями, затем make, опционально make test и установка через make install. Если configure завершается успешно, дальше выполняются make и make install как обычно.

./configure --with-openssl [--with-gnutls --with-wolfssl]
make
make test (optional)
make install

Шаг make test — это запуск набора проверок собранного кода; он помечен как опциональный, потому что для обычной установки достаточно успешной сборки, а тестирование выполняют, когда нужно убедиться в работоспособности сборки.

configure требует явно выбрать TLS-бэкенд, если только TLS не отключён полностью через --without-ssl. Доступные опции выбора: --with-gnutls, --with-mbedtls, --with-openssl (работает и для форков OpenSSL), --with-rustls, --with-wolfssl и --without-ssl. Несколько бэкендов можно указать в одной команде: тогда в собранном curl доступны сразу несколько реализаций TLS, и при работе можно выбрать нужную из них. Принудительная сборка без SSL — ./configure --without-ssl.

Важная деталь про статическую сборку: чтобы получить статическую библиотеку, отключают создание разделяемой через ./configure --disable-shared. При линковке с разделяемыми библиотеками цепочку зависимостей обрабатывает загрузчик библиотек автоматически, а при статической линковке все библиотеки-зависимости нужно предоставить уже в командной строке линковки. Скрипты сборки в основном предполагают, что пользователь сам передаёт все необходимые дополнительные библиотеки через LIBS или LDFLAGS.

Кросс-компиляция под arm64

Общий шаблон кросс-компиляции — ./configure --host=ARCH-OS, где указывается целевая архитектура и ОС. В разделе Cross compile нужно распаковать пакет curl, перейти в новый каталог, установить переменные окружения для кросс-компиляционного тулчейна и вызвать configure с нужными опциями, обязательно указав --host и --build.

Для arm64 (aarch64) приведён конкретный пример:

./configure --host aarch64-linux-android --with-pic --disable-shared

Здесь --host aarch64-linux-android задаёт целевую платформу, --with-pic включает позиционно-независимый код, а --disable-shared отключает сборку разделяемых библиотек.

Для сборки под Android сначала нужно установить Android NDK. При сборке через configure задаются переменные окружения, включая CC и CXX с префиксом aarch64-linux-android29-clang, а также AR, AS, LD, RANLIB и STRIP из toolchain NDK. При сборке на Linux или для других API level и архитектур эти переменные нужно скорректировать.

Альтернативный путь — через cmake, где для aarch64 и API level 29 задаются -DANDROID_ABI=arm64-v8a, -DANDROID_PLATFORM=android-29 и -DCMAKE_TOOLCHAIN_FILE, указывающий на android.toolchain.cmake в NDK, при этом SSL и libpsl отключаются.

Переменные окружения и флаги кросс-компиляции

Переменные CFLAGS и LDFLAGS применяются для передачи опций компилятору и компоновщику, например CFLAGS='-Os -ffunction-sections' и LDFLAGS='-Wl,--gc-sections'. Переменные CPPFLAGS и LDFLAGS используются для указания путей к заголовкам и библиотекам OpenSSL при использовании --with-openssl.

В примере кросс-компиляции под i586-pc-msdosdjgpp задаются переменные CC, AR, RANLIB, WATT_ROOT и флаги --host, --with-openssl, --with-zlib, --without-libpsl, --disable-shared. Для arm64 с OpenSSL в примере указывается --with-openssl="$TOOLCHAIN/sysroot/usr", а при статической линковке в LIBS перечисляются библиотеки, которые нужно подключить вручную: -lssl и -lcrypto — сам SSL/TLS-слой, а -lc++ — стандартная библиотека C++, от которой он зависит.

Предупреждения о несовпадении версий тулчейна

В инструкции для DJGPP есть прямое требование: Watt-32 и OpenSSL должны компилироваться той же версией DJGPP, иначе «things go wrong because things like FS-extensions and errno values have been changed between releases». Это единственное место, где прямо сформулирована связь между несовпадением версий тулчейна и зависимостей и некорректным поведением.

Для arm64 задаётся конкретный тулчейн через переменные окружения, указывающие на конкретные компиляторы и утилиты. Аналогичное несовпадение на arm64 могло бы проявиться, если бы компиляторы и утилиты сборки относились к одному тулчейну, а библиотеки SSL/TLS или их транзитивные зависимости были собраны другим тулчейном.

Компромиссы: переносимость, безопасность, размер

Требование явно выбирать TLS-бэкенд — это компромисс: явный выбор повышает безопасность (не остаёшься без TLS по умолчанию), но снижает переносимость, так как нужно заранее знать доступный бэкенд. Переносимость обеспечивается поддержкой множества ОС (от AIX и AmigaOS до Zephyr) и 28 архитектур CPU, среди которых Alpha, ARC, ARM, AVR32, C-SKY, CompactRISC, Elbrus, ETRAX, HP-PA, Itanium, LoongArch, m68k, m88k, MicroBlaze, MIPS, Nios, OpenRISC, POWER, PowerPC, RISC-V, s390, SH4, SPARC, Tilera, VAX, x86, Xtensa, z/arch. К семейству arm64/aarch64 относятся архитектура ARM как общее название и явно указанные в примерах arm64-v8a и aarch64-linux-android.

Для уменьшения размера бинарника в embedded-приложениях предлагаются опции configure и флаги компилятора. При конфигурировании задаётся CFLAGS с флагами оптимизации; для gcc это как минимум -Os, а также -ffunction-sections и -Wl,--gc-sections среди прочих. Отмечено, что новые компиляторы часто дают меньший код за счёт улучшенной оптимизации. Рекомендуется задавать как можно больше флагов --disable- и --without- для отключения ненужных функций, включая криптографическую аутентификацию (--disable-aws, --disable-basic-auth, --disable-bearer-auth, --disable-digest-auth, --disable-kerberos-auth, --disable-negotiate-auth, --disable-ntlm) и SSL/TLS (--without-ssl).

Уязвимости, связанные с парсерами

В таблице CVE перечислены три уязвимости, относящиеся к разбору входных данных, и во всех случаях речь идёт о чтении за границами буфера:

  • CVE-2024-7264 «ASN.1 date parser overread» — затронуты версии с 7.32.0 по 8.9.0, опубликована 2024-07-31, вознаграждение 540 USD.
  • CVE-2022-35260 «.netrc parser out-of-bounds access» — с 7.84.0 по 7.85.0, опубликована 2022-10-26, вознаграждение 480 USD.
  • CVE-2017-1000101 «URL globbing out of bounds read» — с 7.34.0 по 7.54.1, опубликована 2017-08-09.

Как организована таблица CVE

Записи в таблице организованы как строки с номером, уровень серьёзности (S), метки компонентов (W), признак C (C), названием уязвимости, датой публикации (Published), первой уязвимой версией (First), последней уязвимой версией (Last) и суммой вознаграждения (Awarded). Уровень серьёзности обозначается буквами L, M, H в колонке S, а фильтры над таблицей позволяют показывать «All | Medium+ | High+ | Critical».

Диапазон версий задаётся парой First/Last: например, для CVE-2026-82209 указаны First 7.46.0 и Last 8.21.0, то есть уязвимы версии от 7.46.0 до 8.21.0 включительно. Дата публикации — это дата раскрытия, например 2026-09-02 для нескольких записей сразу, что показывает пакетное раскрытие. Вознаграждение указывается в долларах США и зависит от серьёзности: за L обычно 505 USD, за M — 2540 USD, за H — 4660 USD, хотя встречаются и другие суммы (480, 540, 800, 1000, 1200, 1500, 2000, 2400 USD).

Классификация последствий: CVE-2015-3236 «lingering HTTP credentials in connection reuse» — severity H; CVE-2026-7168 «cross-proxy Digest auth state leak» — severity M.

Время жизни ошибки измеряется диапазоном версий, в которых она существовала: CVE-2024-7264 — от 7.32.0 до 8.9.0, CVE-2022-35260 — от 7.84.0 до 7.85.0, CVE-2020-8286 — от 7.41.0 до 7.73.0. Диапазон может охватывать как несколько минорных выпусков, так и более длительный период.

Что из этого следует на практике

  • TLS-бэкенд нужно выбирать явно. Configure требует этого, если TLS не отключён через --without-ssl. Это осознанный компромисс между безопасностью и переносимостью.
  • Статическая сборка перекладывает зависимости на пользователя. При --disable-shared все библиотеки-зависимости нужно указывать в командной строке линковки через LIBS или LDFLAGS; для arm64 с OpenSSL в примере это LIBS='-lssl -lcrypto -lc++'.
  • Уязвимости парсеров существуют независимо от архитектуры. CVE-2024-7264, CVE-2022-35260 и CVE-2017-1000101 — это чтение за границами буфера при разборе ASN.1-дат, файла .netrc и шаблонов URL. Диапазоны уязвимых версий измеряются годами выпусков.
  • Процесс раскрытия координирован и вознаграждается. Публикации группируются по датам, суммы вознаграждений градируются по уровню серьёзности, а диапазон версий фиксируется парой First/Last.

Источники

Похожее