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