
Фаззит реализации ЦП, генерируя тестовые входные данные из программных прокси, после чего выполняет их на реальном оборудовании для обнаружения дефектов и эррат в микроархитектуре.
SiliFuzz — это система, которая находит дефекты процессоров путём фаззинга программных прокси, таких как симуляторы процессора или дизассемблеры, а затем выполняет накопленные тестовые входные данные (известные как корпус) на реальных процессорах в больших масштабах. SiliFuzz находится в стадии разработки; подробности см. в статье.
Фаззинг — это метод тестирования цели (приложения или API) с помощью большого количества тестовых входных данных, генерируемых на лету. Цель состоит в том, чтобы сделать эти входные данные как можно более интересными и разнообразными для запуска крайних случаев. Другими словами, фаззинг направлен на максимизацию совокупного покрытия кода. Покрытие кода может иметь разные значения, например, какие базовые блоки выполняются или какие пути проходятся в программе.
Для целей SiliFuzz прокси — это любая программная или аппаратная система, которая ведёт себя аналогично некоторым аспектам целевого процессора. Например, эмулятор процессора или дизассемблер. Прокси необходим, когда мы не можем напрямую собирать информацию о покрытии с цели.
Применяя методы фаззинга к прокси, мы можем сгенерировать серию тестовых входных данных (корпус), которые вызывают интересное поведение в прокси. Наше базовое предположение состоит в том, что это приводит к аналогично интересному поведению на цели. Подробнее в документации.
Коллекция входных данных, используемых для тестирования цели, называется корпусом.
Достаточно большой корпус содержит миллионы входных данных и обычно разбивается на несколько непересекающихся фрагментов, называемых сегментами (shards).
Снимок SiliFuzz описывает короткую последовательность инструкций процессора, а также начальное состояние регистров и памяти процессора для детерминированного выполнения этой последовательности. Типичный снимок содержит менее 100 байт кода и выполняется за микросекунды, но может быть сколь угодно большим. Снимки хранятся в виде protocol buffer-сообщений silifuzz.proto.Snapshot.
Снимки обычно создаются из входных данных, сгенерированных фаззинг-движком. Для целей тестирования процессора эти входные данные фильтруются для устранения всех недетерминированных снимков. Подробнее в документации.
Конечное состояние описывает содержимое регистров и памяти, которое ожидается по завершении выполнения снимка. Если снимок выполняется по-разному на разных микроархитектурах процессора, у него будет несколько ожидаемых конечных состояний.
Snap — это представление снимка в памяти, которое может быть легко загружено и выполнено Runner'ом. Snap-файлы обычно загружаются с диска читающим runner'ом. Формат Snap на диске практически идентичен формату в памяти, за исключением того, что нативные указатели заменены смещениями. См. этот заголовочный файл для подробностей. Этот формат часто называют перемещаемым (relocatable). Каждый Snap содержит ровно одно ожидаемое конечное состояние, то есть Snap-файлы специфичны для микроархитектуры. Подробнее в документации.
Runner — это бинарный файл для тестирования одного ядра процессора. Runner потребляет сегмент корпуса, многократно выполняет случайные Snap-ы и проверяет, достигнуто ли ожидаемое конечное состояние. Runner — это однопоточный процесс.
Оркестратор — это процесс, который управляет несколькими runner-ами. В типичной конфигурации оркестратор непрерывно выполняет по одному runner-у на каждое логическое ядро процессора, накапливает и сообщает обо всех сбоях, возникающих в отдельных процессах runner-ов.
Список поддерживаемых микроархитектур см. в этом файле.
SiliFuzz работает на Linux-системах x86_64 и aarch64. Он был протестирован с ядрами Linux версий 5.x и 6.x. Нет гарантии совместимости с более старыми версиями ядра. Устаревший ABI vsyscall должен быть отключён, чтобы избежать ложных срабатываний.
Неполный список ошибок и дефектов, найденных SiliFuzz.
Логический баг — это некорректное поведение процессора, присущее конкретной микроархитектуре или степингу процессора. SiliFuzz выявил следующие баги:
(Электрический) дефект — это некорректное поведение процессора, которое происходит только на одном или нескольких чипах. SiliFuzz обнаружил следующие дефекты, описанные в статье:
git clone https://github.com/google/silifuzz.git && cd silifuzz
SILIFUZZ_SRC_DIR=`pwd`
./install_build_dependencies.sh # Currently, works for the latest Ubuntu only.
bazel build -c opt @silifuzz//tools:{snap_corpus_tool,fuzz_filter_tool,snap_tool,silifuzz_platform_id,simple_fix_tool_main} \
@silifuzz//runner:reading_runner_main_nolibc \
@silifuzz//orchestrator:silifuzz_orchestrator_main
SILIFUZZ_BIN_DIR=`pwd`/bazel-bin
cd "${SILIFUZZ_BIN_DIR}"
ПРИМЕЧАНИЕ: Вы можете использовать Docker-контейнер, чтобы не загрязнять хост-систему: docker run -it --tty --security-opt seccomp=unconfined --mount type=bind,source=${SILIFUZZ_SRC_DIR},target=/app ubuntu:noble /bin/bash -c "cd /app && ./install_build_dependencies.sh && bazel build ... && bazel test ..."
Для Bazel используйте следующие команды.
cd "${SILIFUZZ_SRC_DIR}"
COV_FLAGS_FILE="$(bazel info output_base)/external/fuzztest+/centipede/clang-flags.txt"
bazel build -c opt --copt=-UNDEBUG --dynamic_mode=off \
--per_file_copt=unicorn/.*@$(xargs < "${COV_FLAGS_FILE}" |sed -e 's/,/\\,/g' -e 's/ /,/g') @//proxies:unicorn_x86_64
bazel build -c opt @fuzztest//centipede:centipede
mkdir -p /tmp/wd
# Fuzz the Unicorn proxy under Centipede 1000 times with parallelism of 30.
"${SILIFUZZ_BIN_DIR}/external/fuzztest+/centipede/centipede" \
--binary="${SILIFUZZ_BIN_DIR}/proxies/unicorn_x86_64" \
--workdir=/tmp/wd \
-j=30 --num_runs=1000