diff --git a/debugging-on-linux/build.sh b/debugging-on-linux/build.sh new file mode 100755 index 0000000000000000000000000000000000000000..97fa4f782b043c9de2d1ecb7afaa3b01bea21f4d --- /dev/null +++ b/debugging-on-linux/build.sh @@ -0,0 +1,4 @@ +#!/bin/bash +printf "Building Main Presentation... " +pandoc -t beamer --template template.tex --listings pres.md -o pres.pdf --pdf-engine pdflatex +echo "Done" diff --git a/debugging-on-linux/code/a.out b/debugging-on-linux/code/a.out new file mode 100755 index 0000000000000000000000000000000000000000..35834fedf974406adf04f655fbf137f00524d3ca Binary files /dev/null and b/debugging-on-linux/code/a.out differ diff --git a/debugging-on-linux/code/bugtype/a.out b/debugging-on-linux/code/bugtype/a.out new file mode 100755 index 0000000000000000000000000000000000000000..f1f6de3742b1c8221f5a516f902f00e96b441b57 Binary files /dev/null and b/debugging-on-linux/code/bugtype/a.out differ diff --git a/debugging-on-linux/code/bugtype/bo b/debugging-on-linux/code/bugtype/bo new file mode 100755 index 0000000000000000000000000000000000000000..5d3de3366a6ae1121574d7cc4fb9bcd2f27d9b9a Binary files /dev/null and b/debugging-on-linux/code/bugtype/bo differ diff --git a/debugging-on-linux/code/bugtype/bo.c b/debugging-on-linux/code/bugtype/bo.c new file mode 100644 index 0000000000000000000000000000000000000000..28c76942d032be719f0a378eba47b958ac9d7a17 --- /dev/null +++ b/debugging-on-linux/code/bugtype/bo.c @@ -0,0 +1,7 @@ + +int +main(int argc, char **argv) { + int arr[10]; + arr[11] = 1; + return 0; +} diff --git a/debugging-on-linux/code/bugtype/loi b/debugging-on-linux/code/bugtype/loi new file mode 100755 index 0000000000000000000000000000000000000000..7b5531aeb1f3e1d87edd85083c1610d65aff7786 Binary files /dev/null and b/debugging-on-linux/code/bugtype/loi differ diff --git a/debugging-on-linux/code/bugtype/loi.c b/debugging-on-linux/code/bugtype/loi.c new file mode 100644 index 0000000000000000000000000000000000000000..80be2ebddb952c1cf6a2a690d5a9c0a795beb738 --- /dev/null +++ b/debugging-on-linux/code/bugtype/loi.c @@ -0,0 +1,33 @@ +#include<pthread.h> + +pthread_mutex_t lock1 = PTHREAD_MUTEX_INITIALIZER; +pthread_mutex_t lock2 = PTHREAD_MUTEX_INITIALIZER; + +void * +thread1(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock1); + pthread_mutex_lock(&lock2); //Lock-Order-Inversion between here... + pthread_mutex_unlock(&lock2); + pthread_mutex_unlock(&lock1); + return NULL; +} + +void * +thread2(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock2); + pthread_mutex_lock(&lock1); // ... and here! + pthread_mutex_unlock(&lock1); + pthread_mutex_unlock(&lock2); + return NULL; +} + +int +main(int argc, char **argv) { + pthread_t t1, t2; + pthread_create(&t1, NULL, thread1, NULL); + pthread_create(&t2, NULL, thread2, NULL); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + return 0; +} + diff --git a/debugging-on-linux/code/bugtype/ms b/debugging-on-linux/code/bugtype/ms new file mode 100755 index 0000000000000000000000000000000000000000..181316b0d0e11e9c8cf0adf4dd3cd76a280cb1e0 Binary files /dev/null and b/debugging-on-linux/code/bugtype/ms differ diff --git a/debugging-on-linux/code/bugtype/ms.c b/debugging-on-linux/code/bugtype/ms.c new file mode 100644 index 0000000000000000000000000000000000000000..260cbf4c93f839535eda575c57e181c08a5ae4e4 --- /dev/null +++ b/debugging-on-linux/code/bugtype/ms.c @@ -0,0 +1,8 @@ +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *p; + p = malloc(sizeof(int)); + return 0; +} diff --git a/debugging-on-linux/code/bugtype/rc b/debugging-on-linux/code/bugtype/rc new file mode 100755 index 0000000000000000000000000000000000000000..221f6083cd6cba4d2eebc5dd33b5156976b68232 Binary files /dev/null and b/debugging-on-linux/code/bugtype/rc differ diff --git a/debugging-on-linux/code/bugtype/rc.c b/debugging-on-linux/code/bugtype/rc.c new file mode 100644 index 0000000000000000000000000000000000000000..b2107fbfa71d5624bca1aa68ddbce3e1bf07d79f --- /dev/null +++ b/debugging-on-linux/code/bugtype/rc.c @@ -0,0 +1,20 @@ +#include<pthread.h> + +volatile int inc; + +void * +thread(void *arg __attribute__((unused))) { + for (int i = 0; i < 65536; i++) + inc++; + return NULL; +} + +int +main(int argc, char **argv) { + pthread_t t1, t2; + pthread_create(&t1, NULL, thread, NULL); + pthread_create(&t2, NULL, thread, NULL); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + return 0; +} diff --git a/debugging-on-linux/code/bugtype/uaf b/debugging-on-linux/code/bugtype/uaf new file mode 100755 index 0000000000000000000000000000000000000000..7322d2ed1451ce6fd402284db583b35353e846db Binary files /dev/null and b/debugging-on-linux/code/bugtype/uaf differ diff --git a/debugging-on-linux/code/bugtype/uaf.c b/debugging-on-linux/code/bugtype/uaf.c new file mode 100644 index 0000000000000000000000000000000000000000..a73885b27ea1fc5522d91c4166780efb26f2f628 --- /dev/null +++ b/debugging-on-linux/code/bugtype/uaf.c @@ -0,0 +1,10 @@ +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *ip; + ip = malloc(sizeof(int)); + free(ip); + *ip = 3; + return 0; +} diff --git a/debugging-on-linux/code/bugtype/ud.c b/debugging-on-linux/code/bugtype/ud.c new file mode 100644 index 0000000000000000000000000000000000000000..976c9bb9f617a847cbe05ffa09663aa22ded620d --- /dev/null +++ b/debugging-on-linux/code/bugtype/ud.c @@ -0,0 +1,7 @@ +int +main(int argc, char **argv) { + int i = 32; + int j = 0xCAFFEE; + j = j << i; + return 0; +} diff --git a/debugging-on-linux/code/bugtype/ui b/debugging-on-linux/code/bugtype/ui new file mode 100755 index 0000000000000000000000000000000000000000..c25968b774a43cdcddc5f7f546366b25ec056d23 Binary files /dev/null and b/debugging-on-linux/code/bugtype/ui differ diff --git a/debugging-on-linux/code/bugtype/ui.c b/debugging-on-linux/code/bugtype/ui.c new file mode 100644 index 0000000000000000000000000000000000000000..30c38aa65e8981bdfc9b1ee0b8d498250782bb46 --- /dev/null +++ b/debugging-on-linux/code/bugtype/ui.c @@ -0,0 +1,11 @@ +#include<stdio.h> + +int +main(int argc, char **argv) { + int i; + if (i) + printf("Hui\n"); + else + printf("Pfui\n"); + return 0; +} diff --git a/debugging-on-linux/code/gdb-examples/a.out b/debugging-on-linux/code/gdb-examples/a.out new file mode 100755 index 0000000000000000000000000000000000000000..b84cf7b2ebc6cadabfd56be72f1b70d82d73e386 Binary files /dev/null and b/debugging-on-linux/code/gdb-examples/a.out differ diff --git a/debugging-on-linux/code/gdb-examples/simple.c b/debugging-on-linux/code/gdb-examples/simple.c new file mode 100644 index 0000000000000000000000000000000000000000..3eff185b058d57ac86fc0b08012f24a63f131756 --- /dev/null +++ b/debugging-on-linux/code/gdb-examples/simple.c @@ -0,0 +1,24 @@ + +#include<stdio.h> +#include<stdbool.h> +#include<tgmath.h> + +bool +is_prime(int number) { + int max = ((int) sqrt((double) number)) + 1; + for (int i = 2; i < max; i++) + if (!(number % i)) + return false; + return true; +} + +int +main(int argc, char** argv) { + int number; + scanf("%d", &number); + if (is_prime(number)) + printf("%d: prime\n", number); + else + printf("%d: not prime\n", number); + return 0; +} diff --git a/debugging-on-linux/code/strace/a.out b/debugging-on-linux/code/strace/a.out new file mode 100755 index 0000000000000000000000000000000000000000..378ed288782c4cd84b90ac3aa25d3768e527e2b5 Binary files /dev/null and b/debugging-on-linux/code/strace/a.out differ diff --git a/debugging-on-linux/code/strace/file.c b/debugging-on-linux/code/strace/file.c new file mode 100644 index 0000000000000000000000000000000000000000..babd1485625571b7517a0604512172db2baff524 --- /dev/null +++ b/debugging-on-linux/code/strace/file.c @@ -0,0 +1,10 @@ +#include<stdio.h> + +int +main(int argc, char **argv) { + FILE *f = fopen("/tmp/test", "w+"); + fprintf(f, "Hello\n"); + fclose(f); + printf("Done!\n"); + return 0; +} diff --git a/debugging-on-linux/code/strace/simple.c b/debugging-on-linux/code/strace/simple.c new file mode 100644 index 0000000000000000000000000000000000000000..e3ebf471c920e2b6ff5e39dca8a07bb60b3a0ce3 --- /dev/null +++ b/debugging-on-linux/code/strace/simple.c @@ -0,0 +1,7 @@ +#include<stdio.h> + +int +main(int argc, char **argv) { + printf("Hello World!"); + return 0; +} diff --git a/debugging-on-linux/img/gdb-tui.orig.png b/debugging-on-linux/img/gdb-tui.orig.png new file mode 100644 index 0000000000000000000000000000000000000000..f5c625ee420357a88c4b2853bd14de9b401a6cef Binary files /dev/null and b/debugging-on-linux/img/gdb-tui.orig.png differ diff --git a/debugging-on-linux/img/gdb-tui.png b/debugging-on-linux/img/gdb-tui.png new file mode 100644 index 0000000000000000000000000000000000000000..4043169e54b53b778f131d0080a2d241bc5a7d28 Binary files /dev/null and b/debugging-on-linux/img/gdb-tui.png differ diff --git a/debugging-on-linux/img/logo_blue.pdf b/debugging-on-linux/img/logo_blue.pdf new file mode 100644 index 0000000000000000000000000000000000000000..dd60efc4c6899371b6086d097bd64d744d55b127 Binary files /dev/null and b/debugging-on-linux/img/logo_blue.pdf differ diff --git a/debugging-on-linux/img/logo_white.pdf b/debugging-on-linux/img/logo_white.pdf new file mode 100644 index 0000000000000000000000000000000000000000..74e15f9b659f0609691256ad2075f21bec24882a Binary files /dev/null and b/debugging-on-linux/img/logo_white.pdf differ diff --git a/debugging-on-linux/pres.md b/debugging-on-linux/pres.md new file mode 100644 index 0000000000000000000000000000000000000000..5214115e3fb82bdb68822a523682c113167ea1b6 --- /dev/null +++ b/debugging-on-linux/pres.md @@ -0,0 +1,870 @@ +## + +\begin{center} + {\Large \textbf{Debugging on Linux}} +\end{center} + +## Print Debugging + +\begin{center} +Most often, debugging is done via print... \linebreak + +...But that scales poorly +\end{center} + +## GDB + +\begin{center} +A Debugger (such as GDB) can help here +\end{center} + +# GDB + +## What is GDB? + +GDB is a tool to inspect your program while it is running. It allows: + +- to stop program execution at any point +- step through the program +- print the value of variables +- modify variables + +## Usage + +Before running a program in GDB, it needs to be compiled with debug symbol. + +- Available compiler flags flags are `-g`, `-g3`, `-ggdb3` +- `-ggdb3` gives the most debug information + +The program can then be run under gdb: `gdb ./a.out` + + +## An Example... + +```{.c .numberLines} +#include<stdio.h> +#include<stdbool.h> +#include<tgmath.h> + +bool is_prime(int number) { /* snip */ } + +int +main(int argc, char** argv) { + int number; + scanf("%d", &number); + if (is_prime(number)) + printf("%d: prime\n", number); + else + printf("%d: not prime\n", number); + return 0; +} +``` + +## An Example... + + +``` +$ gcc -ggdb3 simple.c -lm +$ gdb ./a.out +GNU gdb (GDB) 8.3.1 +Copyright (C) 2019 Free Software Foundation, Inc. +...snip... +For help, type "help". +Type "apropos word" to search for commands related to "word"... +Reading symbols from ./a.out... +(gdb) +``` + +## The Start Command + +start +: starts program execution and stops it at the beginning of main + + +``` +(gdb) start +Temporary breakpoint 1 at 0x11c7: file simple.c, line 16. +Starting program: /home/dcm/misc/debugging-on-linux/code/gdb-examples/a.out + +Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdf18) at simple.c:16 +16 main(int argc, char** argv) { +(gdb) +``` + +## The Step Command + +step +: executes the next line. If there's a function, it will step into it. + + +``` +(gdb) start +Temporary breakpoint 1 at 0x11c7: file simple.c, line 16. +Starting program: /home/dcm/misc/debugging-on-linux/code/gdb-examples/a.out + +Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdf18) at simple.c:16 +16 main(int argc, char** argv) { +(gdb) step +18 scanf("%d", &number); +(gdb) +``` +## The Next Command + +next +: executes the next line. If there's a function, *DO NOT* step into it. + + +``` +(gdb) start +Temporary breakpoint 1 at 0x11c7: file simple.c, line 16. +Starting program: /home/dcm/misc/debugging-on-linux/code/gdb-examples/a.out + +Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdf18) at simple.c:16 +16 main(int argc, char** argv) { +(gdb) step +18 scanf("%d", &number); +(gdb) next +1234567 +19 if (is_prime(number)) +(gdb) +``` + +## The Print Command + +print +: prints the contents of variables. It also allows calling functions. + + +``` +(gdb) step +18 scanf("%d", &number); +(gdb) next +1234567 +19 if (is_prime(number)) +(gdb) print number +$1 = 1234567 +(gdb) print is_prime(number) +$2 = false +(gdb) +``` + +## The List Command + +list +: lists the 10 lines of source code surrounding the current one + +``` +(gdb) next +1234567 +19 if (is_prime(number)) +(gdb) list +14 +15 int +16 main(int argc, char** argv) { +17 int number; +18 scanf("%d", &number); +19 if (is_prime(number)) +20 printf("%d: prime\n", number); +21 else +22 printf("%d: not prime\n", number); +23 return 0; +(gdb) + +``` + +## The Break Command + +break +: adds a break point, which will stop program execution when reached + +``` +(gdb) list +14 +15 int +16 main(int argc, char** argv) { +17 int number; +18 scanf("%d", &number); +19 if (is_prime(number)) +20 printf("%d: prime\n", number); +21 else +22 printf("%d: not prime\n", number); +23 return 0; +(gdb) break 22 +Breakpoint 2 at 0x555555555214: file simple.c, line 22. +(gdb) +``` + +## The Continue Command + +continue +: continues program execution until either a breakpoint is hit or the programs exits + +``` +(gdb) break 22 +Breakpoint 2 at 0x555555555214: file simple.c, line 22. +(gdb) continue +Continuing. + +Breakpoint 2, main (argc=1, argv=0x7fffffffdf08) at simple.c:22 +22 printf("%d: not prime\n", number); +(gdb) +``` + +## The Quit Command + +quit +: quits GDB, terminating the program + +``` +(gdb) continue +Continuing. + +Breakpoint 2, main (argc=1, argv=0x7fffffffdf08) at simple.c:22 +22 printf("%d: not prime\n", number); +(gdb) quit +A debugging session is active. + + Inferior 1 [process 7431] will be killed. + +Quit anyway? (y or n) y +$ +``` + +## Text User Interface + +GDB can also be run with a TUI: `gdb -tui ./a.out` + +## Text User Interface + +\begin{center} +\includegraphics[width=0.75\textwidth]{img/gdb-tui.png} +\end{center} + +# Valgrind + +## Quick Warning + +_The following is slide code and output, therefore all source code and program output is heavily shortend._ + +## Valgrind + +- Collection of usefull debugging tools + - Memcheck + - Helgrind +- Works on any executable + - Doesn't require recompilation + - Output gets more readable with debug symbols! + +## How to use Valgrind? + +- (optionally) Recompile the program with debug symbols +- Choose a tool +- Run the program under valgrind: `valgrind --tool=$TOOL ./a.out` + +# Memcheck + +## Memcheck + +- finds common memory errors + - Use after free + - Use of uninitialised values + - Memory leaks + - ...and many more +- Usage: `valgrind [--leak-check=full] ./a.out` + +## Use After Free + +Use After Free +: Usage of a pointer after it has been `free()`'d + +## Use After Free + + +```{.c .numberLines} +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *ip; + ip = malloc(sizeof(int)); + free(ip); + *ip = 3; + return 0; +} +``` + +## Use After Free + + +``` +==4474== Memcheck, a memory error detector +..snip.. +==4474== Invalid write of size 4 +==4474== at 0x109176: main (uaf.c:8) +==4474== Address 0x4a86040 is 0 bytes inside a block of size 4 free'd +==4474== at 0x48399AB: free (vg_replace_malloc.c:540) +==4474== by 0x109171: main (uaf.c:7) +==4474== Block was alloc'd at +==4474== at 0x483877F: malloc (vg_replace_malloc.c:309) +==4474== by 0x109161: main (uaf.c:6) +==4474== +..snip.. +``` + +## Uninitialized Values + +Unitialized Values +: Use of a variable or memory before it has been initialized + +## Uninitialized Values + +```{.c .numberLines} +#include<stdio.h> + +int +main(int argc, char **argv) { + int i; + if (i) + printf("Hui\n"); + else + printf("Pfui\n"); + return 0; +} +``` + +## Uninitialized Values + +``` +==7096== Memcheck, a memory error detector +..snip.. +==7096== Conditional jump or move depends on uninitialised value(s) +==7096== at 0x10914C: main (ui.c:6) +==7096== +Pfui +==7096== +..snip.. + +``` + +## Memory Leaks + +Memory Leak +: A piece of memory is `malloc()`'d, but never `free()`'d + +## Memory Leaks + +```{.c .numberLines} +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *p; + p = malloc(sizeof(int)); + return 0; +} + +``` + +## Memory Leaks + +``` +==7219== Memcheck, a memory error detector +..snip.. +==7219== HEAP SUMMARY: +==7219== in use at exit: 4 bytes in 1 blocks +==7219== total heap usage: 1 allocs, 0 frees, 4 bytes allocated +==7219== +==7219== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1 +==7219== at 0x483877F: malloc (vg_replace_malloc.c:309) +==7219== by 0x109151: main (ms.c:6) +==7219== +==7219== LEAK SUMMARY: +==7219== definitely lost: 4 bytes in 1 blocks +==7219== indirectly lost: 0 bytes in 0 blocks +==7219== possibly lost: 0 bytes in 0 blocks +==7219== still reachable: 0 bytes in 0 blocks +==7219== suppressed: 0 bytes in 0 blocks +..snip.. +``` +# Helgrind + +## Helgrind + +- finds common threading problems + - Potential lock order inversions + - Race conditions +- Has problems with lock-free data structures/algorithms +- Usage: `valgrind --tool=helgrind ./a.out` + +## Race Condition + +Race Condition +: Several Threads try to modify the same variable at the same time yielding unexpected results + +## Race Condition + +```{.c .numberLines} +#include<pthread.h> + +volatile int inc; + +void * +thread(void *arg __attribute__((unused))) { + for (int i = 0; i < 65536; i++) + inc++; + return NULL; +} + +int +main(int argc, char **argv) { + pthread_t t1, t2; + pthread_create(&t1, NULL, thread, NULL); + pthread_create(&t2, NULL, thread, NULL); + /* snip */ +} + +``` + +## Race Condition + +``` +==7454== Helgrind, a thread error detector +..snip.. +==7454== Possible data race during read of size 4 at 0x10C03C by thread #3 +==7454== Locks held: none +==7454== at 0x10915A: thread (rc.c:8) +==7454== by 0x483F876: mythread_wrapper (hg_intercepts.c:389) +==7454== by 0x48A84CE: start_thread (in /usr/lib/libpthread-2.30.so) +==7454== by 0x49C02D2: clone (in /usr/lib/libc-2.30.so) +==7454== +==7454== This conflicts with a previous write of size 4 by thread #2 +==7454== Locks held: none +==7454== at 0x109163: thread (rc.c:8) +==7454== by 0x483F876: mythread_wrapper (hg_intercepts.c:389) +==7454== by 0x48A84CE: start_thread (in /usr/lib/libpthread-2.30.so) +==7454== by 0x49C02D2: clone (in /usr/lib/libc-2.30.so) +==7454== Address 0x10c03c is 0 bytes inside data symbol "inc" +..snip.. +``` + +## Lock Order Inversion + +Lock Order Inversion +: Two threads try to acquire two locks in opposite orders + +## Lock Order Inversion + +```{.c .numberLines startFrom="6"} +void * +thread1(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock1); + pthread_mutex_lock(&lock2); //Lock-Order-Inversion between here... + pthread_mutex_unlock(&lock2); + pthread_mutex_unlock(&lock1); + return NULL; +} + +void * +thread2(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock2); + pthread_mutex_lock(&lock1); // ... and here! + pthread_mutex_unlock(&lock1); + pthread_mutex_unlock(&lock2); + return NULL; +} +``` + +## Lock Order Inversion + +``` +==8617== Thread #3: lock order "0x10C080 before 0x10C0C0" violated +==8617== +==8617== Observed (incorrect) order is: acquisition of lock at 0x10C0C0 +==8617== at 0x483CC3F: mutex_lock_WRK (hg_intercepts.c:909) +==8617== by 0x1091C3: thread2 (loi.c:17) +..snip.. +==8617== followed by a later acquisition of lock at 0x10C080 +==8617== at 0x483CC3F: mutex_lock_WRK (hg_intercepts.c:909) +==8617== by 0x1091CF: thread2 (loi.c:18) +..snip.. +==8617== Required order was established by acquisition of lock at 0x10C080 +==8617== at 0x483CC3F: mutex_lock_WRK (hg_intercepts.c:909) +==8617== by 0x109180: thread1 (loi.c:8) +..snip.. +==8617== followed by a later acquisition of lock at 0x10C0C0 +==8617== at 0x483CC3F: mutex_lock_WRK (hg_intercepts.c:909) +==8617== by 0x10918C: thread1 (loi.c:9) +``` + +# Sanitizer + +## Sanitizer + +- Error checking compiled into binary + - Thread Sanitizer + - Address Sanitizer + - Undefined Behaviour Sanitizer +- needs recompilation! +- Largely covers the same things as valgrind +- Available for both GCC and LLVM + +## How to use Sanitizer? + +- Recompile the program with the Sanitizer enabled + - Needs to be enabled everywhere + - Usage: `gcc -ggdb3 -fsanitize=$SANITIZER` +- run the resulting binary + +# Address + +## Sanitizer - Address + +- Checks for all kinds of address violations +- Also includes leak detector +- Similiar to valgrind's Memcheck + - Can detect some bugs memcheck can't + - Can't detect some bugs memcheck can + - Provides more information +- Usage `gcc -fsanitize=address` + +## Use After Free + +```{.c .numberLines} +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *ip; + ip = malloc(sizeof(int)); + free(ip); + *ip = 3; + return 0; +} +``` + +## Use After Free + +``` +==4299==ERROR: AddressSanitizer: heap-use-after-free on address 0x602000000010 at pc 0x5630686c61d9 bp 0x7ffda2c5a820 sp 0x7ffda2c5a810 +WRITE of size 4 at 0x602000000010 thread T0 + #0 0x5630686c61d8 in main /home/dcm/misc/debugging-on-linux/code/bugtype/uaf.c:8 + +0x602000000010 is located 0 bytes inside of 4-byte region [0x602000000010,0x602000000014) +freed by thread T0 here: + #1 0x5630686c61a1 in main /home/dcm/misc/debugging-on-linux/code/bugtype/uaf.c:7 + +previously allocated by thread T0 here: + #1 0x5630686c6191 in main /home/dcm/misc/debugging-on-linux/code/bugtype/uaf.c:6 +``` + +## Use After Free +``` +SUMMARY: AddressSanitizer: heap-use-after-free /home/dcm/misc/debugging-on-linux/code/bugtype/uaf.c:8 in main +Shadow bytes around the buggy address: + 0x0c047fff7fb0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0x0c047fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +=>0x0c047fff8000: fa fa[fd]fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8010: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa + 0x0c047fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa +``` + +## Memory Leak + + +```{.c .numberLines} +#include<stdlib.h> + +int +main(int argc, char **argv) { + int *p; + p = malloc(sizeof(int)); + return 0; +} + +``` + +## Memory Leaks + +``` +================================================================= +==4545==ERROR: LeakSanitizer: detected memory leaks + +Direct leak of 4 byte(s) in 1 object(s) allocated from: + #0 0x7f9b5971faca in __interceptor_malloc /build/gcc/src/gcc/libsanitizer/asan/asan_malloc_linux.cc:144 + #1 0x55d960688171 in main /home/dcm/misc/debugging-on-linux/code/bugtype/ms.c:6 + #2 0x7f9b5946f152 in __libc_start_main (/usr/lib/libc.so.6+0x27152) + +SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s). +``` + +## Buffer Overflow + +Buffer Overflow +: Reading or writing memory outside of an allocated buffer + +## Buffer Overflow +```{.c .numberLines} +int +main(int argc, char **argv) { + int arr[10]; + arr[11] = 1; + return 0; +} +``` + +## Buffer Overflow + +``` +==4464==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7ffe66905e4c at pc 0x564ce591325c bp 0x7ffe66905dd0 sp 0x7ffe66905dc0 +WRITE of size 4 at 0x7ffe66905e4c thread T0 + #0 0x564ce591325b in main /home/dcm/misc/debugging-on-linux/code/bugtype/bo.c:5 + #1 0x7f0a22d6b152 in __libc_start_main (/usr/lib/libc.so.6+0x27152) + #2 0x564ce59130ad in _start (/home/dcm/misc/debugging-on-linux/code/bugtype/a.out+0x10ad) + +Address 0x7ffe66905e4c is located in stack of thread T0 at offset 92 in frame + #0 0x564ce5913188 in main /home/dcm/misc/debugging-on-linux/code/bugtype/bo.c:3 + + This frame has 1 object(s): + [48, 88) 'arr' (line 4) <== Memory access at offset 92 overflows this variable +``` + +# Thread + +## Sanitizer - Thread + +- Detects common threading problems +- Similiar to valgrind's Helgrind +- Always run programs with `TSAN_OPTIONS=second_deadlock_stack=1` + - `$ TSAN_OPTIONS=second_deadlock_stack=1 ./a.out` +- Usage `gcc -fsanitize=thread` + +## Lock Order Inversion + +```{.c .numberLines startFrom="6"} +void * +thread1(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock1); + pthread_mutex_lock(&lock2); //Lock-Order-Inversion between here... + pthread_mutex_unlock(&lock2); + pthread_mutex_unlock(&lock1); + return NULL; +} + +void * +thread2(void *arg __attribute__((unused))) { + pthread_mutex_lock(&lock2); + pthread_mutex_lock(&lock1); // ... and here! + pthread_mutex_unlock(&lock1); + pthread_mutex_unlock(&lock2); + return NULL; +} +``` + +## Lock Order Inversion + +``` +WARNING: ThreadSanitizer: lock-order-inversion (potential deadlock) (pid=7033) + Cycle in lock order graph: M9 (0x55fc4d1620a0) => M10 (0x55fc4d1620e0) => M9 + + Mutex M10 acquired here while holding mutex M9 in thread T1: + #1 thread1 /home/dcm/misc/debugging-on-linux/code/bugtype/loi.c:9 + + Mutex M9 previously acquired by the same thread here: + #1 thread1 /home/dcm/misc/debugging-on-linux/code/bugtype/loi.c:8 + + Mutex M9 acquired here while holding mutex M10 in thread T2: + #1 thread2 /home/dcm/misc/debugging-on-linux/code/bugtype/loi.c:18 + + Mutex M10 previously acquired by the same thread here: + #1 thread2 /home/dcm/misc/debugging-on-linux/code/bugtype/loi.c:17 +``` + +## Race Condition + +```{.c .numberLines} +#include<pthread.h> + +volatile int inc; + +void * +thread(void *arg __attribute__((unused))) { + for (int i = 0; i < 65536; i++) + inc++; + return NULL; +} + +int +main(int argc, char **argv) { + pthread_t t1, t2; + pthread_create(&t1, NULL, thread, NULL); + pthread_create(&t2, NULL, thread, NULL); + /* snip */ +} + +``` + +## Race condition + +``` +WARNING: ThreadSanitizer: data race (pid=11607) + Read of size 4 at 0x559e8e885074 by thread T2: + #0 thread /home/dcm/misc/debugging-on-linux/code/bugtype/rc.c:8 + + Previous write of size 4 at 0x559e8e885074 by thread T1: + #0 thread /home/dcm/misc/debugging-on-linux/code/bugtype/rc.c:8 + + Location is global 'inc' of size 4 at 0x559e8e885074 (a.out+0x000000004074) + + Thread T2 (tid=11610, running) created by main thread at: + #1 main /home/dcm/misc/debugging-on-linux/code/bugtype/rc.c:16 + + Thread T1 (tid=11609, finished) created by main thread at: + #1 main /home/dcm/misc/debugging-on-linux/code/bugtype/rc.c:15 +``` + +# Undefined Behaviour + +## Sanitizer - Undefined Behaviour + +- Detects undefined behaviour in C +- Doesn't cover undefined behaviour related to memory +- Usage `gcc -fsanitize=undefined` + +## Undefined Bitshifts + +Undefined Bitshift +: Bitshifts larger than the width of the integer type + +## Undefined Bitshifts + +```{.c .numberLines} +int +main(int argc, char **argv) { + int i = 32; + int j = 0xCAFFEE; + j = j << i; + return 0; +} +``` + +## Undefined Bitshifts + +``` +ud.c:5:9: runtime error: shift exponent 32 is too large for 32-bit type 'int' +``` + +# Strace + +## Strace + +- Shows all system calls made by a program +- Allows debugging of everything File related + - Which files are used by a program? + - Where does a program search for files? + - What does a program do with a file? +- Usage: `strace ./a.out` + +## Some important Linux Systemcalls + +| System Call | Function | Return Value | +|-------------|--------------|-------------------------------| +| `openat` | Opens a file | A filedescriptor for the file | +| `close` | Close a file | 0 | +| `read` | Reads from a file | Number of bytes read | +| `write` | Writes to a files | Number of bytes written | +| `mmap` | Maps a file into memory | Pointer to memory | +| `socket` | Creates a new socket | A filedescriptor for the socket | +| `clone` | Spawn new thread/process | ID of the newly create Process/Thread | +| `execve` | Load new Program | 0 | +| `exit_group` | Exit | N/A | + +## An Example... + +```{.c .numberLines} +#include<stdio.h> + +int +main(int argc, char **argv) { + printf("Hello World!"); + return 0; +} +``` +## An Example... +``` +$ strace ./a.out > /dev/null +execve("./a.out", ["./a.out"], 0x7ffee24755b0 /* 47 vars */) = 0 +brk(NULL) = 0x55fd00b9c000 +--snip-- +fstat(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(0x1, 0x3), ...}) = 0 +ioctl(1, TCGETS, 0x7fff3fb75ac0) = -1 ENOTTY (Inappropriate ioctl for device) +brk(NULL) = 0x55fd00b9c000 +brk(0x55fd00bbd000) = 0x55fd00bbd000 +write(1, "Hello World!", 12) = 12 +exit_group(0) = ? ++++ exited with 0 +++ +``` +## Filtering output + +- strace allows for filtering output by syscall +- Syntax: `strace -e $ARGUMENT` + - ARGUMENT should be a comma seperated list of systemcalls + - if a syscall is prefixed by `!`, it means all systemcalls but it + +## An Example... + +``` +$ strace -e write ./a.out +write(1, "Hello World!", 12Hello World!) = 12 ++++ exited with 0 +++ +``` + +## Files associated with File descriptors + +- Enabled by `-y` +- Will show the file associated with each file descriptor +- `/dev/pts/*` is standart output + +## An Example + +```{.c .numberLines} +#include<stdio.h> + +int +main(int argc, char **argv) { + FILE *f = fopen("/tmp/test", "w+"); + fprintf(f, "Hello\n"); + fclose(f); + printf("Done!\n"); + return 0; +} +``` + +## An Example + +``` +$ strace -y -e openat,write,close ./a.out >/dev/null +openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3</etc/ld.so.cache> +close(3</etc/ld.so.cache>) = 0 +openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3</usr/lib/libc-2.30.so> +close(3</usr/lib/libc-2.30.so>) = 0 +openat(AT_FDCWD, "/tmp/test", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3</tmp/test> +write(3</tmp/test>, "Hello\n", 6) = 6 +close(3</tmp/test>) = 0 +write(1</dev/null>, "Done!\n", 6) = 6 ++++ exited with 0 +++ +``` +## + +\begin{center} + \textbf{Thank you for your attention!} +\end{center} + +\begin{center} + \textbf{Question?} +\end{center} diff --git a/debugging-on-linux/pres.pdf b/debugging-on-linux/pres.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5c139d7db48f712fea06ede141d9c8f89bd6fc46 Binary files /dev/null and b/debugging-on-linux/pres.pdf differ diff --git a/debugging-on-linux/template.tex b/debugging-on-linux/template.tex new file mode 100644 index 0000000000000000000000000000000000000000..53563c5b71418f03c7931b7f25c823f2576c4d9f --- /dev/null +++ b/debugging-on-linux/template.tex @@ -0,0 +1,191 @@ +\documentclass[aspectratio=169,12pt]{beamer} +\usepackage{lmodern} +\usepackage[T1]{fontenc} %pipes don't display properly without this +\usepackage[utf8]{inputenc} +\usepackage{listings} +\usepackage{color} +\usepackage{datapie} +\usepackage{multicol} +\usepackage{siunitx} %pretty measurement unit rendering +\usepackage{hyperref} %enable hyperlink for urls +\usepackage{caption} % needed to tweak caption size +\usepackage{booktabs} +\usepackage{longtable} +\usepackage{graphicx} + +\newcommand{\passthrough}[1]{#1} + +\usefonttheme[onlymath]{serif} +\setcounter{MaxMatrixCols}{20} + +\DeclareSIUnit\pixel{px} + +\usecolortheme[RGB={37,68,113}]{structure} +\usetheme{Dresden} + +\newenvironment{figurehere} +{\def\@captype{figure}} +{} +\makeatother + +%commands to exclude sections from miniframes +\makeatletter +\let\beamer@writeslidentry@miniframeson=\beamer@writeslidentry +\def\beamer@writeslidentry@miniframesoff{% + \expandafter\beamer@ifempty\expandafter{\beamer@framestartpage}{}% does not happen normally + {%else + % removed \addtocontents commands + \clearpage\beamer@notesactions% + } +} +\newcommand*{\miniframeson}{\let\beamer@writeslidentry=\beamer@writeslidentry@miniframeson} +\newcommand*{\miniframesoff}{\let\beamer@writeslidentry=\beamer@writeslidentry@miniframesoff} +\beamer@compresstrue +\makeatother + + +\providecommand{\tightlist}{% + \setlength{\itemsep}{0pt}\setlength{\parskip}{0pt}} + + +%various gray colors +\definecolor{slg}{gray}{0.25} +\definecolor{lg}{gray}{0.55} +\definecolor{vlg}{gray}{0.73} +\definecolor{tlg}{gray}{0.9} + +%TheAlt colors +\definecolor{ldorange}{HTML}{F18A20} +\colorlet{ldbright}{ldorange!70!white} % tinted version of orange, used in miniframes +\definecolor{ldblue}{HTML}{254471} + +%%Theme colors +%\definecolor{thgreen}{HTML}{A1A92C} +%\definecolor{thmauve}{HTML}{97284D} + +%Theme colors +\definecolor{thgreen}{HTML}{539727} +\definecolor{thmauve}{HTML}{572272} + +%reduce caption font size: +\captionsetup{font={scriptsize,color=lg}} + +%do not prepend numbering/lettering to figures/subfigures +\captionsetup{labelformat=empty} %do not prepend letters to figure captions + +%Apply TheAlt colors to theme + % section titles in top navigation bar +\setbeamercolor{section in head/foot}{parent=palette tertiary,fg=ldorange} +\setbeamertemplate{section in head/foot shaded}{\color{ldbright}\usebeamertemplate{section in head/foot}} + % miniframes (little navigation circles) +\setbeamercolor*{mini frame}{fg=ldorange,bg=ldbright} +\setbeamertemplate{mini frame in other section}[default][0] +\setbeamertemplate{mini frame in other subsection}[default][0] + % others +\setbeamercolor{author in head/foot}{fg=white} +\setbeamercolor{subsection in head/foot}{fg=white} +\setbeamercolor{caption name}{fg=vlg} +\setbeamercolor{caption}{fg=vlg} +\setbeamercolor{frametitle}{fg=ldblue} + +\setbeamertemplate{caption}{\raggedright\insertcaption\par} +\setbeamertemplate{navigation symbols}{} +\setbeamertemplate{bibliography item}[text] + +\definecolor{mygreen}{rgb}{0,0.6,0} +\definecolor{mygray}{rgb}{0.5,0.5,0.5} +\definecolor{mymauve}{rgb}{0.58,0,0.82} + +\lstdefinestyle{custombash}{ + belowcaptionskip=1\baselineskip, + captionpos=, + breaklines=true, + frame=L, + xleftmargin=\parindent, + language=bash, + morestring=[b]', + morekeywords=[2]{sudo,zypper,notify-send,feh,youtube-dl,sort,tee,head,tail,shuf,mpv,find,convert,xrandr,curl,wget,grep,xdotool,rm,cp,mv,touch,bash,chmod,mkdir,rsync,mplayer,mpv,xdotool,jshon}, + showstringspaces=false, + basicstyle=\scriptsize\ttfamily, + rulecolor=\color{tlg}, + backgroundcolor=\color{tlg}, + fillcolor=\color{tlg}, + rulesepcolor=\color{tlg}, + commentstyle=\itshape\color{thmauve!60!black}, + keywordstyle=\bfseries\color{thgreen}, + identifierstyle=\color{ldblue}, + stringstyle=\color{thmauve} +} + +\lstset{ + style=custombash, + caption={Descriptive Caption Text}, + label=DescriptiveLabel +} + +$if(title)$ +\title{$title$} +$endif$ +$if(subtitle)$ +\subtitle{$subtitle$} +$endif$ +$if(author)$ +\author{$for(author)$$author$$sep$ \and $endfor$} +$endif$ + +\institute{\includegraphics[width=0.35\textwidth]{img/logo_blue.pdf}} +\date{$date$} + +\renewcommand{\emph}[1]{\textcolor{ldorange}{#1}} +\let\oldtextbf\textbf +\renewcommand{\textbf}[1]{\textcolor{ldorange}{\oldtextbf{#1}}} +\newcommand{\soft}[1]{\textcolor{lg}{#1}} +\newcommand{\textt}[1]{\textcolor{blue}{\texttt{#1}}} +\newcommand{\bigtext}[1]{\centering\Huge \textbf{\textcolor{ldorange}{#1}}\normalsize} + +%shortcut to insert small logo in footline +\def\logo{% + \resizebox{!}{3ex}{\includegraphics{img/logo_white.pdf}} +} + +% Define a custom footline that includes our logo +\setbeamertemplate{footline} +{% + \begin{beamercolorbox}[wd=\paperwidth,ht=2.5ex,dp=1.125ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{title in head/foot} + \usebeamerfont{title in head/foot}% + \insertshorttitle\hfill\insertframenumber + \end{beamercolorbox} + \begin{beamercolorbox}[wd=\paperwidth,ht=3.5ex,dp=1.625ex,% + leftskip=.3cm,rightskip=.3cm plus1fil]{author in head/foot} + \usebeamerfont{author in head/foot} + \raisebox{0.5ex}{\insertshortauthor}\hfill\raisebox{-0.5ex}{\logo} + \end{beamercolorbox} +} + +\begin{document} + +$if(title)$ +\frame{\titlepage} +$endif$ + +$for(include-before)$ +$include-before$ + +$endfor$ + +$if(toc)$ +\begin{frame} +\tableofcontents[hideallsubsections] +\end{frame} + +$endif$ + +$body$ + +$for(include-after)$ +$include-after$ + +$endfor$ + +\end{document}