]> git.ipfire.org Git - thirdparty/systemd.git/blame - docs/TESTING_WITH_SANITIZERS.md
docs: place all our markdown docs in rough categories
[thirdparty/systemd.git] / docs / TESTING_WITH_SANITIZERS.md
CommitLineData
c9a95378
FS
1---
2title: Testing systemd using sanitizers
4cdca0af 3category: Contributing
c9a95378
FS
4---
5
6# Testing systemd using sanitizers
7
8To catch the *nastier* kind of bugs, you can run your code with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
9and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
10This is mostly done automagically by various CI systems for each PR, but you may
11want to do it locally as well. The process slightly varies depending on the
12compiler you want to use and which part of the test suite you want to run.
13
14## gcc
15gcc compiles in sanitizer libraries dynamically by default, so you need to get
16the shared libraries first - on Fedora these are shipped as a separate packages
17(`libasan` for Address Sanitizer and `libubsan` for Undefined Behavior Sanitizer).
18
19The compilation itself is then a matter of simply adding `-Db_sanitize=address,undefined`
20to `meson`. That's it - following executions of `meson test` and integrations tests
21under `test/` subdirectory will run with sanitizers enabled. However, to get
22truly useful results, you should tweak the runtime configuration of respective
23sanitizers; e.g. in systemd we set the following environment variables:
24
25```bash
26ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
27UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
28```
29## clang
30In case of clang things are somewhat different - the sanitizer libraries are
31compiled in statically by default. This is not an issue if you plan to run
32only the unit tests, but for integration tests you'll need to convince clang
33to use the dynamic versions of sanitizer libraries.
34
35First of all, pass `-shared-libsan` to both `clang` and `clang++`:
36
37```bash
38CFLAGS=-shared-libasan
39CXXFLAGS=-shared-libasan
40```
41
42The `CXXFLAGS` are necessary for `src/libsystemd/sd-bus/test-bus-vtable-cc.c`. Compilation
43is then the same as in case of gcc, simply add `-Db_sanitize=address,undefined`
44to the `meson` call and use the same environment variables for runtime configuration.
45
46```bash
47ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
48UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
49```
50
51After this, you'll probably notice that all compiled binaries complain about
52missing `libclang_rt.asan*` library. To fix this, you have to install clang's
53runtime libraries, usually shipped in the `compiler-rt` package. As these libraries
54are installed in a non-standard location (non-standard for `ldconfig`), you'll
55need to manually direct binaries to the respective runtime libraries.
56
57```
58# Optionally locate the respective runtime DSO
59$ ldd build/systemd | grep libclang_rt.asan
60 libclang_rt.asan-x86_64.so => not found
61 libclang_rt.asan-x86_64.so => not found
62$ find /usr/lib* /usr/local/lib* -type f -name libclang_rt.asan-x86_64.so 2>/dev/null
63/usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so
64
65# Set the LD_LIBRARY_PATH accordingly
66export LD_LIBRARY_PATH=/usr/lib64/clang/7.0.1/lib/
67
68# If the path is correct, the "not found" message should change to an actual path
69$ ldd build/systemd | grep libclang_rt.asan
70 libclang_rt.asan-x86_64.so => /usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so (0x00007fa9752fc000)
71```
72
73This should help binaries to correctly find necessary sanitizer DSOs.
74
75Also, to make the reports useful, `llvm-symbolizer` tool is required (usually
76part of the `llvm` package).
77
78## Background notes
79The reason why you need to force dynamic linking in case of `clang` is that some
80applications make use of `libsystemd`, which is compiled with sanitizers as well.
81However, if a *standard* (uninstrumented) application loads an instrumented library,
82it will immediately fail due to unresolved symbols. To fix/workaround this, you
83need to pre-load the ASan DSO using `LD_PRELOAD=/path/to/asan/dso`, which will
84make things work as expected in most cases. This will, obviously, not work with
85statically linked sanitizer libraries.
86
87These shenanigans are performed automatically when running the integration test
88suite (i.e. `test/TEST-??-*`) and are located in `test/test-functions` (mainly,
89but not only, in the `create_asan_wrapper` function).