
DR.CHECKER : Ein Soundy Schwachstellenerkennungstool für Linux-Kernel-Treiber

Dieses Repository enthält alle Quellen, einschließlich der Setup-Skripte. Jetzt mit einer fantastischen Benutzeroberfläche, um die Warnungen zusammen mit den zugehörigen Quelldateien anzuzeigen.
Ubuntu >= 14.04.5 LTS
16. Feb. 2018:
Siehe das Dokument Docker-Verwendung für Details zur Nutzung von DR.CHECKER in einem vorgefertigten Docker-Container.
Unsere Implementierung basiert auf LLVM, genauer gesagt LLVM 3.8. Wir benötigen außerdem Werkzeuge wie c2xml, um Header zu parsen.
Stellen Sie zunächst sicher, dass Sie cmake (wird von Setup-/Build-Skripten verwendet) und libxml (erforderlich für c2xml) installiert haben:
sudo apt-get install cmake libxml2-dev
Als nächstes haben wir ein einzelnes Skript erstellt, das alle erforderlichen Werkzeuge herunterlädt und baut.
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.
Beispiel:
python setup_drchecker.py -o drchecker_deps
Um das Setup abzuschließen, benötigen Sie außerdem Änderungen an Ihrer lokalen PATH-Umgebungsvariable. Das Setup-Skript gibt Ihnen die genauen Änderungen an, die Sie vornehmen müssen.
Dies hängt vom erfolgreichen Abschluss des Setups ab. Wir haben ein einzelnes Skript, das alles baut, bitte sehr.
cd llvm_analysis
./build.sh
Dies hängt vom erfolgreichen Abschluss des Bauens ab. Um DR.CHECKER auf Kernel-Treibern auszuführen, müssen wir diese zunächst in LLVM-Bitcode konvertieren.
Zuerst benötigen wir einen baubaren Kernel. Das bedeutet, Sie sollten den Kernel mit dem normalen Build-Setup kompilieren können, d.h. make.
Wir erfassen zunächst die Ausgabe des make-Befehls, aus dieser Ausgabe extrahieren wir den genauen Kompilierungsbefehl.
make (oder makeout.txt)Übergeben Sie einfach V=1 und leiten Sie die Ausgabe in die Datei um.
Beispiel:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
HINWEIS: VERWENDEN SIE KEINE MEHREREN PROZESSE, d.h. -j. Die Ausführung im Mehrprozessormodus führt zu einer fehlerhaften Ausgabedatei, da mehrere Prozesse versuchen, in die Ausgabedatei zu schreiben.
Das war's. DR.CHECKER kümmert sich ab hier um alles.
Es gibt mehrere Schritte, um die DR.CHECKER-Analyse auszuführen, alle diese Schritte sind in einem einzigen Skript helper_scripts/runner_scripts/run_all.py zusammengefasst.
So führen Sie es aus:
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.
Das Skript baut, verlinkt und führt DR.CHECKER auf allen Treibern aus, was erhebliche Zeit (45 min - 90 min) in Anspruch nehmen kann. Wenn Sie DR.CHECKER manuell auf einzelnen Treibern ausführen möchten, lesen Sie standalone.
Das obige Skript führt die folgenden Aufgaben im Mehrprozessormodus aus, um alle CPU-Kerne zu nutzen:
Alle generierten Bitcode-Dateien werden in dem Ordner abgelegt, der dem Argument -l übergeben wurde.
Dieser Schritt nimmt erhebliche Zeit in Anspruch, abhängig von der Anzahl Ihrer Kerne.
Wenn Sie diesen Schritt bereits durchgeführt haben, können Sie ihn durch Angabe von -skb überspringen.
Dies führt das Verlinken durch, es durchläuft alle Bitcode-Dateien und identifiziert die zugehörigen Bitcode-Dateien, die verlinkt werden müssen, und verlinkt sie (mittels llvm-link) zu einer konsolidierten Bitcode-Datei (die neben der entsprechenden Bitcode-Datei gespeichert wird).
Ähnlich wie beim obigen Schritt können Sie diesen Schritt durch Angabe von -skl überspringen.
Dieser Schritt sucht nach den Einstiegspunktdeklarationen in den Header-Dateien und speichert deren Konfiguration in der Datei: hdr_file_config.txt im LLVM-Build-Verzeichnis.
Zum Überspringen: -skp
Dieser Schritt identifiziert alle Einstiegspunkte in allen konsolidierten Treiber-Bitcode-Dateien.
Die Ausgabe wird in der Datei: entry_point_out.txt im LLVM-Build-Verzeichnis gespeichert.
Beispiel für den Inhalt der Datei 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
Zum Überspringen: -ske
Dieser Schritt führt DR.CHECKER auf allen Einstiegspunkten in der Datei entry_point_out.txt aus. Die Ausgabe für jeden Einstiegspunkt wird in dem Ordner gespeichert, der für die Option -f angegeben wurde.
Zum Überspringen: -ski
Nun zeigen wir ein Beispiel vom Punkt, an dem Sie Kernel-Quellen haben, bis zum Erhalt von Schwachstellenwarnungen.
Wir haben einen Mediatek-Kernel 33.2.A.3.123.tar.bz2 hochgeladen. Laden Sie die obige Datei zunächst herunter und entpacken Sie sie.
Angenommen, Sie haben die obige Datei in einem Ordner namens ~/mediatek_kernel entpackt.
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
Der obige Befehl nimmt einige Zeit (30 min - 1 Std.) in Anspruch.
Zunächst befinden sich alle Analyseergebnisse im Ordner: ~/mediatek_kernel/dr_checker_out (Argument für die Option -f), für jeden Einstiegspunkt wird eine .json-Datei erstellt, die alle Warnungen im JSON-Format enthält. Diese json-Dateien enthalten nach Kontexten organisierte Warnungen.
Zweitens enthält der Ordner ~/mediatek_kernel/dr_checker_out/instr_warnings (bezogen auf das Argument für die Option -f) Warnungen, die nach Anweisungsposition organisiert sind.
Diese Warnungen können mit unserem Visualizer analysiert werden.
Schließlich wird eine Zusammenfassung aller Warnungen für jeden Einstiegspunkt, organisiert nach Typ, in die Ausgabe-CSV-Datei geschrieben: ~/mediatek_kernel/dr_checker_out/warnings_stats.csv (bezogen auf das Argument für die Option -f).
-gUm einen Wert für die Option -g anzugeben, müssen Sie den Namen des *-gcc-Binärprogramms kennen, das zum Kompilieren des Kernels verwendet wurde.
Eine einfache Möglichkeit, dies herauszufinden, besteht darin, in makeout.txt nach gcc zu grep; Sie werden Compiler-Befehle sehen, aus denen Sie den Namen des *-gcc-Binärprogramms ableiten können.
Für unser obiges Beispiel: Wenn Sie grep gcc makeout.txt für den Beispiel-Build ausführen, werden Sie viele Zeilen wie die folgende sehen:
aarch64-linux-android-gcc -Wp,-MD,fs/jbd2/.transaction.o.d -nostdinc -isystem ...
Daher sollte der Wert für -g aarch64-linux-android-gcc lauten.
Wenn der zu bauende Kernel 32-Bit ist, wird das Binärprogramm höchstwahrscheinlich arm-eabi-gcc sein.
-aAbhängig vom Chipsatz-Typ müssen Sie die entsprechende Nummer angeben.
-oDies ist der Pfad des Ordners, der der Option O= für den make-Befehl während des Kernel-Builds übergeben wurde.
Nicht alle Kernel benötigen einen separaten Ausgabepfad. Sie können den Kernel bauen, indem Sie die Option O nicht angeben; in diesem Fall SOLLTEN SIE KEINEN Wert für diese Option angeben, während Sie run_all.py ausführen.
Wir bieten eine webbasierte Benutzeroberfläche zur Anzeige aller Warnungen. Bitte lesen Sie Visualisierung.
Sie können einen oder mehrere Schwachstellenprüfer deaktivieren, indem Sie die entsprechenden #define DISABLE_*-Zeilen in BugDetectorDriver.cpp auskommentieren.
Nach Ihren Wünschen stellen wir auch ein Skript zur Nachbearbeitung der Ergebnisse bereit. Schauen Sie es sich an.
Viel Spaß!!