Outils pour utilisateurs

Outils du site


prog:sanitizer

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentesRévision précédente
prog:sanitizer [2024/11/12 12:47] – ↷ Nom de la page changé de prog:llvm-sanitizer à prog:sanitizer rootprog:sanitizer [2024/11/12 12:56] (Version actuelle) – Fusion de deux pages concernant les sanitazers root
Ligne 2: Ligne 2:
  
 Pour que les sanitizers fonctionnent bien, il est très fortement recommandé (imposé par Visual Studio) de compiler le projet et toutes ces dépendances. Pour que les sanitizers fonctionnent bien, il est très fortement recommandé (imposé par Visual Studio) de compiler le projet et toutes ces dépendances.
 +
 +Il existe ''-fsanitize=address,thread,undefined'' mais ''address'' et ''thread'' ne sont pas compatible simultanément.
  
 ====memory==== ====memory====
 +
 +Détecte l'utilise de mémoire non initialisée.
 +
 <code c main.c> <code c main.c>
 int main(int argc, char **argv) { int main(int argc, char **argv) {
Ligne 38: Ligne 43:
 Pour l'instrumenter, il faut suivre les instructions de [[https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo|MemorySanitizerLibcxxHowTo]] {{ :prog:clang:memorysanitizerlibcxxhowto_google_sanitizers_wiki_2020-02-13_22_56_51_.html |Archive du 29/01/2016 le 13/02/2020}} Pour l'instrumenter, il faut suivre les instructions de [[https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo|MemorySanitizerLibcxxHowTo]] {{ :prog:clang:memorysanitizerlibcxxhowto_google_sanitizers_wiki_2020-02-13_22_56_51_.html |Archive du 29/01/2016 le 13/02/2020}}
  
-Ma tentative : +====Control Flow Integrity====
-  * unwind de gcc sans sanitize : [[https://github.com/llvm-mirror/libunwind/blob/master/docs/BuildingLibunwind.rst|Building libunwind]] {{ :prog:clang:libunwind_buildinglibunwind.rst_at_master_llvm-mirror_libunwind_2020-02-13_22_58_36_.html |Archive du 29/01/2019 le 13/02/2020}} +
-  * libc++ and libc++abi avec -fsanitizer ([[https://github.com/google/sanitizers/wiki/MemorySanitizerLibcxxHowTo|MemorySanitizerLibcxxHowTo]]). Ajouter ''LDFLAGS=%%"%%-L .../llvm-project/build/lib/clang/8.0.0/x86_64-unknown-linux-gnu/lib -lunwind%%"%%'' si nécessaire. +
-  * compilation de poppler avec libc++ de clang [[https://github.com/google/oss-fuzz/blob/master/projects/poppler/build.sh]] +
-<code bash> +
-LDFLAGS="-L .../llvm-project/build/lib/clang/8.0.0/x86_64-unknown-linux-gnu/lib -lunwind -L.../llvm-project_libcxx_msan/build/lib -lc++abi" +
-CFLAGS="-fsanitize=memory -fno-omit-frame-pointer -fsanitize-memory-track-origins=2 -stdlib=libc++ -I.../llvm-project_libcxx_msan/build/include -I.../llvm-project_libcxx_msan/build/include/c++/v1" +
-CXXFLAGS="-fsanitize=memory -fno-omit-frame-pointer -fsanitize-memory-track-origins=2 -stdlib=libc++ -I.../llvm-project_libcxx_msan/build/include -I.../llvm-project_libcxx_msan/build/include/c++/v1" cmake .. +
--DCMAKE_BUILD_TYPE=debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ +
-</code> +
-  * Compilation du programme de test sans succès : +
-<code> +
-clang++ +
--L .../llvm-project/build/lib/clang/8.0.0/x86_64-unknown-linux-gnu/lib -lunwind +
--L .../llvm-project_libcxx_msan/build/lib -lc++abi +
--fsanitize=memory,fuzzer -stdlib=libc++ +
--I.../llvm-project_libcxx_msan/build/include -I.../llvm-project_libcxx_msan/build/include/c++/v1 +
--I ~/info/programmation/poppler/cpp/ +
-pdf_fuzzer.cc -o fuzz_target +
--L ~/info/programmation/poppler/build/ -lpoppler +
--L ~/info/programmation/poppler/build/cpp/ -lpoppler-cpp +
-</code>+
  
-====Control Flow Integrity==== 
 [[https://www.usenix.org/sites/default/files/conference/protected-files/enigma_slides_serebryany.pdf|Sanitize, Fuzz, and Harden Your C++ Code]], {{ :prog:clang:enigma_slides_serebryany.pdf |Archive}} [[https://www.usenix.org/sites/default/files/conference/protected-files/enigma_slides_serebryany.pdf|Sanitize, Fuzz, and Harden Your C++ Code]], {{ :prog:clang:enigma_slides_serebryany.pdf |Archive}}
  
Ligne 145: Ligne 128:
  
 [[prog:valgrind|valgrind]] détecte l'erreur. [[prog:valgrind|valgrind]] détecte l'erreur.
 +
 +
 +====address====
 +Il détecte des erreurs de type global-buffer-overflow, heap-use-after-free.
 +[[https://www.youtube.com/watch?v=qTkYDA0En6U|CppCon 2015: Kostya Serebryany “Beyond Sanitizers, Fuzzing and Hardening your C++ apps for Security and Reliability”]]
 +
 +  * global-buffer-overflow
 +<file c main.c>
 +int global_array[100] = {-1};
 +
 +int main(int argc, char **argv) {
 +  return global_array[argc+100];
 +}
 +</file>
 +
 +  gcc main.c -g -fsanitize=address -fno-omit-frame-pointer -o main && ./main
 +
 +  =================================================================
 +  ==2500==ERROR: AddressSanitizer: global-buffer-overflow on address 0x000000740cf4 at pc 0x00000050d9bf bp 0x7ffeabb89b70 sp 0x7ffeabb89b68
 +  READ of size 4 at 0x000000740cf4 thread T0
 +      #0 0x50d9be in main /tmp/main.c:4:10
 +      #1 0x7f1208faa461 in __libc_start_main .../sys-libs/glibc-2.25-r9/work/glibc-2.25/csu/../csu/libc-start.c:295
 +      #2 0x419709 in _start (/tmp/main+0x419709)
 +  
 +  0x000000740cf4 is located 4 bytes to the right of global variable 'global_array' defined in 'main.c:1:5' (0x740b60) of size 400
 +  SUMMARY: AddressSanitizer: global-buffer-overflow /tmp/main.c:4:10 in main
 +  Shadow bytes around the buggy address:
 +    0x0000800e0140: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e0150: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e0160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e0170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e0180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +  =>0x0000800e0190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00[f9]f9
 +    0x0000800e01a0: f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 f9 00 00 00 00
 +    0x0000800e01b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e01c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e01d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0000800e01e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +  Shadow byte legend (one shadow byte represents 8 application bytes):
 +    Addressable:           00
 +    Partially addressable: 01 02 03 04 05 06 07 
 +    Heap left redzone:       fa
 +    Freed heap region:       fd
 +    Stack left redzone:      f1
 +    Stack mid redzone:       f2
 +    Stack right redzone:     f3
 +    Stack after return:      f5
 +    Stack use after scope:   f8
 +    Global redzone:          f9
 +    Global init order:       f6
 +    Poisoned by user:        f7
 +    Container overflow:      fc
 +    Array cookie:            ac
 +    Intra object redzone:    bb
 +    ASan internal:           fe
 +    Left alloca redzone:     ca
 +    Right alloca redzone:    cb
 +  ==2500==ABORTING
 +
 +[[prog:valgrind|valgrind]] ne détecte pas l'erreur.
 +
 +  * heap-use-after-free
 +<file c main2.cc>
 +int main(int argc, char **argv) {
 +  int *array = new int[100];
 +  delete [] array;
 +  return array[argc];
 +}
 +</file>
 +
 +  g++ main2.c -g -fsanitize=address -fno-omit-frame-pointer -o main2 && ./main2
 +
 +  =================================================================
 +  ==2765==ERROR: AddressSanitizer: heap-use-after-free on address 0x614000000044 at pc 0x000000512445 bp 0x7ffd51684f60 sp 0x7ffd51684f58
 +  READ of size 4 at 0x614000000044 thread T0
 +      #0 0x512444 in main /tmp/main2.c:4:10
 +      #1 0x7fd8d0086461 in __libc_start_main .../sys-libs/glibc-2.25-r9/work/glibc-2.25/csu/../csu/libc-start.c:295
 +      #2 0x419d29 in _start (/tmp/main2+0x419d29)
 +  
 +  0x614000000044 is located 4 bytes inside of 400-byte region [0x614000000040,0x6140000001d0)
 +  freed by thread T0 here:
 +      #0 0x50ef30 in operator delete[](void*) .../sys-libs/compiler-rt-sanitizers-5.0.0/work/compiler-rt-5.0.0.src/lib/asan/asan_new_delete.cc:141
 +      #1 0x5123f6 in main /tmp/main2.c:3:3
 +      #2 0x7fd8d0086461 in __libc_start_main .../sys-libs/glibc-2.25-r9/work/glibc-2.25/csu/../csu/libc-start.c:295
 +      #3 0x419d29 in _start (/tmp/main2+0x419d29)
 +    
 +  previously allocated by thread T0 here:
 +      #0 0x50e1c8 in operator new[](unsigned long) .../sys-libs/compiler-rt-  sanitizers-5.0.0/work/compiler-rt-5.0.0.src/lib/asan/asan_new_delete.cc:95
 +      #1 0x5123d4 in main /tmp/main2.c:2:16
 +      #2 0x7fd8d0086461 in __libc_start_main .../sys-libs/glibc-2.25-r9/work/glibc-2.25/csu/../csu/libc-start.c:295
 +      #3 0x419d29 in _start (/tmp/main2+0x419d29)
 +  
 +  SUMMARY: AddressSanitizer: heap-use-after-free /tmp/main2.c:4:10 in main
 +  Shadow bytes around the buggy address:
 +    0x0c287fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0c287fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0c287fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0c287fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0c287fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +  =>0x0c287fff8000: fa fa fa fa fa fa fa fa[fd]fd fd fd fd fd fd fd
 +    0x0c287fff8010: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 +    0x0c287fff8020: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
 +    0x0c287fff8030: fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa
 +    0x0c287fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
 +    0x0c287fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
 +
 +[[prog:valgrind|valgrind]] détecte l'erreur.
 +
 +  ==2787== Command: ./main2
 +  ==2787== 
 +  ==2787== Invalid read of size 4
 +  ==2787==    at 0x4005AF: main (main2.c:4)
 +  ==2787==  Address 0x5b25c84 is 4 bytes inside a block of size 400 free'd
 +  ==2787==    at 0x4C2CAA5: operator delete[](void*) (vg_replace_malloc.c:621)
 +  ==2787==    by 0x4005A6: main (main2.c:3)
 +  ==2787==  Block was alloc'd at
 +  ==2787==    at 0x4C2BAC8: operator new[](unsigned long) (vg_replace_malloc.c:423)
 +  ==2787==    by 0x400584: main (main2.c:2)
 +
 +  * stack-use-after-return
 +<file c main3.c>
 +int *g;
 +
 +void LeakLocal() {
 +  int local;
 +  g = &local;
 +}
 +
 +int main(){
 +  LeakLocal();
 +  return *g;
 +}
 +</file>
 +
 +  gcc main3.c -g -o main3 -fsanitize=address -fno-omit-frame-pointer
 +  ASAN_OPTIONS=detect_stack_use_after_return=1 ./main3
 +
 +L'utilisation de ''ASAN_OPTIONS=detect_stack_use_after_return=1'' est nécessaire car cette option peut créer des faux positifs.
 +
 +  =================================================================
 +  ==2907==ERROR: AddressSanitizer: stack-use-after-return on address 0x7f57b2a00020 at pc 0x00000050db25 bp 0x7ffe8dfc7330 sp 0x7ffe8dfc7328
 +  READ of size 4 at 0x7f57b2a00020 thread T0
 +      #0 0x50db24 in main /tmp/main3.c:10:10
 +      #1 0x7f57b604d461 in __libc_start_main .../sys-libs/glibc-2.25-r9/work/glibc-2.25/csu/../csu/libc-start.c:295
 +      #2 0x419709 in _start (/tmp/main3+0x419709)
 +  
 +  Address 0x7f57b2a00020 is located in stack of thread T0 at offset 32 in frame
 +      #0 0x50d95f in LeakLocal /tmp/main3.c:3
 +  
 +    This frame has 1 object(s):
 +      [32, 36) 'local' (line 4) <== Memory access at offset 32 is inside this variable
 +  HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
 +        (longjmp and C++ exceptions *are* supported)
 +  SUMMARY: AddressSanitizer: stack-use-after-return /tmp/main3.c:10:10 in main
 +  Shadow bytes around the buggy address:
 +    0x0feb76537fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76537fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76537fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76537fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76537ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +  =>0x0feb76538000: f5 f5 f5 f5[f5]f5 f5 f5 00 00 00 00 00 00 00 00
 +    0x0feb76538010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76538020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76538030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76538040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +    0x0feb76538050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 +
 +[[prog:valgrind|valgrind]] détecte l'erreur.
 +
 +  valgrind --track-origins=yes ./main3
 +
 +  ==2961== Syscall param exit_group(status) contains uninitialised byte(s)
 +  ==2961==    at 0x4F002B8: _Exit (_exit.c:31)
 +  ==2961==    by 0x4E70423: __run_exit_handlers (exit.c:98)
 +  ==2961==    by 0x4E704DC: exit (exit.c:105)
 +  ==2961==    by 0x4E58468: (below main) (libc-start.c:329)
 +  ==2961==  Uninitialised value was created by a stack allocation
 +  ==2961==    at 0x4004A4: main (main3.c:10)
 +
 +====thread====
 +<file cpp main4.cc>
 +#include <thread>
 +
 +int main() {
 +  int x;
 +  std::thread t([&]{x=42;});
 +  x = 43;
 +  t.join();
 +
 +  return 0;
 +}
 +</file>
 +
 +  g++ -std=c++11 main4.c -g -o main4 -fsanitize=thread -fno-omit-frame-pointer
 +
 +<WRAP center round important 60%>
 +Le plantage reste aléatoire et il est nécessaire de lancer l'application plusieurs fois.
 +</WRAP>
 +
 +  ==================
 +  WARNING: ThreadSanitizer: data race (pid=3226)
 +    Write of size 4 at 0x7ffd04d5b144 by thread T1:
 +      #0 operator() /tmp/main4.c:5 (main4+0x000000400d0b)
 +      #1 __invoke_impl<void, main()::<lambda()> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include/g++-v7/bits/invoke.h:60 (main4+0x000000401171)
 +      #2 __invoke<main()::<lambda()> > /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include/g++-v7/bits/invoke.h:95 (main4+0x000000400e30)
 +      #3 _M_invoke<0> /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include/g++-v7/thread:234 (main4+0x0000004014b5)
 +      #4 operator() /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include/g++-v7/thread:243 (main4+0x000000401448)
 +      #5 _M_run /usr/lib/gcc/x86_64-pc-linux-gnu/7.2.0/include/g++-v7/thread:186 (main4+0x0000004013ee)
 +      #6 <null> <null> (libstdc++.so.6+0x0000000e251e)
 +  
 +    Previous write of size 4 at 0x7ffd04d5b144 by main thread:
 +      #0 main /tmp/main4.c:6 (main4+0x000000400d75)
 +  
 +    Location is stack of main thread.
 +  
 +    Thread T1 (tid=3228, running) created by main thread at:
 +      #0 pthread_create <null> (libtsan.so.0+0x00000002917a)
 +      #1 std::thread::_M_start_thread(std::unique_ptr<std::thread::_State, std::default_delete<std::thread::_State> >, void (*)()) <null> (libstdc++.so.6+0x0000000e288c)
 +      #2 main /tmp/main4.c:5 (main4+0x000000400d69)
 +  
 +  SUMMARY: ThreadSanitizer: data race /tmp/main4.c:5 in operator()
 +  ==================
 +  ThreadSanitizer: reported 1 warnings
 +
 +[[prog:valgrind|valgrind]] ne détecte pas l'erreur.
 +
 +===undefined===
 +<file c main5.c>
 +int main(int argc, char **argv) {
 +  int t = argc << 16;
 +  return t*t;
 +}
 +</file>
 +
 +  gcc -fsanitize=undefined -fno-sanitize-recover=all -fno-omit-frame-pointer main5.c -g -o main5
 +
 +  main6.c:3:11: runtime error: signed integer overflow: 65536 * 65536 cannot be represented in type 'int'
 +
 +[[prog:valgrind|valgrind]] ne détecte pas l'erreur.
  
 =====Erreurs===== =====Erreurs=====
prog/sanitizer.1731412057.txt.gz · Dernière modification : 2024/11/12 12:47 de root