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