
DR.CHECKER : Инструмент обнаружения уязвимостей Soundy для драйверов ядра Linux

Этот репозиторий содержит все исходники, включая скрипты настройки. Теперь с удивительным UI для просмотра предупреждений вместе с соответствующими исходными файлами.
Ubuntu >= 14.04.5 LTS
16 февраля 2018:
Обратитесь к документу Docker Usage для подробностей об использовании DR.CHECKER в предварительно собранном Docker-контейнере.
Наша реализация основана на LLVM, а именно LLVM 3.8. Нам также нужны инструменты, такие как c2xml, для разбора заголовочных файлов.
Сначала убедитесь, что у вас есть cmake (используется скриптами настройки/сборки) и libxml (требуется для c2xml):
sudo apt-get install cmake libxml2-dev
Затем мы создали единый скрипт, который загружает и собирает все необходимые инструменты.
cd helper_scripts
python setup_drchecker.py --help
usage: setup_drchecker.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help show this help message and exit
-b TARGET_BRANCH Branch (i.e. version) of the LLVM to setup. Default:
release_38 e.g., release_38
-o OUTPUT_FOLDER Folder where everything needs to be setup.
Пример:
python setup_drchecker.py -o drchecker_deps
Для завершения настройки вам также потребуется изменить локальную переменную окружения PATH. Скрипт настройки покажет точные изменения, которые нужно сделать.
Это зависит от успешного завершения Настройки. У нас есть единый скрипт, который собирает всё; пожалуйста.
cd llvm_analysis
./build.sh
Это зависит от успешного завершения Сборки. Чтобы запустить DR.CHECKER на драйверах ядра, нам нужно сначала преобразовать их в LLVM байткод.
Сначала нам нужно иметь собираемое ядро. Это означает, что вы должны иметь возможность скомпилировать ядро, используя обычную настройку сборки, т.е. make.
Мы сначала захватываем вывод команды make, из этого вывода мы извлекаем точную команду компиляции.
make (или makeout.txt)Просто передайте V=1 и перенаправьте вывод в файл.
Пример:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
ПРИМЕЧАНИЕ: НЕ ИСПОЛЬЗУЙТЕ НЕСКОЛЬКО ПРОЦЕССОВ, т.е. -j. Запуск в многопроцессорном режиме испортит выходной файл, так как несколько процессов пытаются записывать в него.
Вот и всё. DR.CHECKER позаботится обо всём остальном.
Есть несколько шагов для запуска анализа DR.CHECKER, все эти шаги упакованы в один скрипт helper_scripts/runner_scripts/run_all.py
Как запустить:
python run_all.py --help
usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT] [-k KERNEL_SRC_DIR] [-skb] [-skl] [-skp] [-ske] [-ski] [-f SOUNDY_ANALYSIS_OUT]
optional arguments:
-h, --help show this help message and exit
-l LLVM_BC_OUT Destination directory where all the generated bitcode files should be stored.
-a CHIPSET_NUM Chipset number. Valid chipset numbers are:
1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT Path to the makeout.txt file.
-g COMPILER_NAME Name of the compiler used in the makeout.txt, This is
needed to filter out compilation commands. Ex: aarch64-linux-android-gcc
-n ARCH_NUM Destination architecture, 32 bit (1) or 64 bit (2).
-o OUT Path to the out folder. This is the folder, which
could be used as output directory during compiling
some kernels. (Note: Not all kernels needs a separate out folder)
-k KERNEL_SRC_DIR Base directory of the kernel sources.
-skb Skip LLVM Build (default: not skipped).
-skl Skip Dr Linker (default: not skipped).
-skp Skip Parsing Headers (default: not skipped).
-ske Skip Entry point identification (default: not
skipped).
-ski Skip Soundy Analysis (default: not skipped).
-f SOUNDY_ANALYSIS_OUT Path to the output folder where the soundy analysis output should be stored.
Скрипт собирает, компонует и запускает DR.CHECKER на всех драйверах, поэтому может занять значительное время (45–90 мин). Если вы хотите запустить DR.CHECKER вручную на отдельных драйверах, обратитесь к standalone.
Вышеуказанный скрипт выполняет следующие задачи в многопроцессорном режиме, чтобы использовать все ядра CPU:
-l.
Этот шаг занимает значительное время, в зависимости от количества имеющихся у вас ядер. Итак, если вы уже выполнили этот шаг, вы можете пропустить его, передав -skb.llvm-link) в единый файл байткода (который будет сохранён рядом с соответствующим файлом байткода).Аналогично предыдущему шагу, вы можете пропустить этот шаг, передав -skl.
hdr_file_config.txt в каталоге сборки LLVM.
Чтобы пропустить: -skpentry_point_out.txt в каталоге сборки LLVM.
Пример содержимого файла entry_point_out.txt:FileRead:hidraw_read:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
FileWrite:hidraw_write:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
IOCTL:hidraw_ioctl:/home/drchecker/33.2.A.3.123/llvm_bc_out/drivers/hid/llvm_link_final/final_to_check.bc
Чтобы пропустить: -ske
entry_point_out.txt. Результат для каждой точки входа будет сохранён в папке, указанной для опции -f.
Чтобы пропустить: -skiТеперь мы покажем пример от момента, когда у вас есть исходники ядра, до получения предупреждений об уязвимостях.
Мы загрузили ядро mediatek 33.2.A.3.123.tar.bz2. Сначала скачайте и распакуйте указанный файл.
Допустим, вы распаковали файл в папку с именем: ~/mediatek_kernel
cd ~/mediatek_kernel
source ./env.sh
cd kernel-3.18
# the following step may not be needed depending on the kernel
mkdir out
make O=out ARCH=arm64 tubads_defconfig
# this following command copies all the compilation commands to makeout.txt
make V=1 -j8 O=out ARCH=arm64 > makeout.txt 2>&1
cd <repo_path>/helper_scripts/runner_scripts
python run_all.py -l ~/mediatek_kernel/llvm_bitcode_out -a 1 -m ~/mediatek_kernel/kernel-3.18/makeout.txt -g aarch64-linux-android-gcc -n 2 -o ~/mediatek_kernel/kernel-3.18/out -k ~/mediatek_kernel/kernel-3.18 -f ~/mediatek_kernel/dr_checker_out
Вышеуказанная команда занимает некоторое время (30 мин - 1 час).
Во-первых, все результаты анализа будут находиться в папке: ~/mediatek_kernel/dr_checker_out (аргумент, указанный в опции -f), для каждой точки входа будет создан файл .json, содержащий все предупреждения в формате JSON. Эти файлы json содержат предупреждения, сгруппированные по контекстам.
Во-вторых, папка ~/mediatek_kernel/dr_checker_out/instr_warnings (относительно аргумента, указанного в опции -f) содержит предупреждения, сгруппированные по местоположению инструкции.
Эти предупреждения можно проанализировать с помощью нашего Visualizer.
Наконец, сводка всех предупреждений для каждой точки входа, сгруппированных по типу, будет записана в выходной CSV-файл: ~/mediatek_kernel/dr_checker_out/warnings_stats.csv (относительно аргумента, указанного в опции -f).
-gЧтобы указать значение для опции -g, вам нужно знать имя бинарного файла *-gcc, используемого для компиляции ядра.
Простой способ узнать это — выполнить grep для gcc в makeout.txt, и вы увидите команды компилятора, из которых можно узнать имя бинарного файла *-gcc.
Для нашего примера выше, если вы выполните grep gcc makeout.txt для примера сборки, вы увидите много строк, подобных приведённым ниже:
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d -nostdinc -isystem ...
Итак, значение для -g должно быть aarch64-linux-android-gcc.
Если собираемое ядро 32-битное, то бинарный файл, скорее всего, будет arm-eabi-gcc
-aВ зависимости от типа чипсета вам нужно указать соответствующий номер.
-oЭто путь к папке, указанной для опции O= команды make во время сборки ядра.
Не все ядра требуют отдельного выходного пути. Вы можете собрать ядро, не указывая опцию O, и в этом случае вы НЕ ДОЛЖНЫ указывать значение для этой опции при запуске run_all.py.
Мы предоставляем веб-интерфейс для просмотра всех предупреждений. Пожалуйста, обратитесь к Visualization.
Вы можете отключить одну или несколько проверок уязвимостей, раскомментировав соответствующие строки #define DISABLE_* в BugDetectorDriver.cpp
По вашему желанию, мы также предоставляем скрипт для постобработки результатов. Ознакомьтесь.
Удачи!!