summaryrefslogtreecommitdiffstats
path: root/docs/TESTING_WITH_SANITIZERS.md
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 13:00:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-27 13:00:47 +0000
commit2cb7e0aaedad73b076ea18c6900b0e86c5760d79 (patch)
treeda68ca54bb79f4080079bf0828acda937593a4e1 /docs/TESTING_WITH_SANITIZERS.md
parentInitial commit. (diff)
downloadsystemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.tar.xz
systemd-2cb7e0aaedad73b076ea18c6900b0e86c5760d79.zip
Adding upstream version 247.3.upstream/247.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'docs/TESTING_WITH_SANITIZERS.md')
-rw-r--r--docs/TESTING_WITH_SANITIZERS.md90
1 files changed, 90 insertions, 0 deletions
diff --git a/docs/TESTING_WITH_SANITIZERS.md b/docs/TESTING_WITH_SANITIZERS.md
new file mode 100644
index 0000000..2622682
--- /dev/null
+++ b/docs/TESTING_WITH_SANITIZERS.md
@@ -0,0 +1,90 @@
+---
+title: Testing systemd Using Sanitizers
+category: Contributing
+layout: default
+---
+
+# Testing systemd Using Sanitizers
+
+To catch the *nastier* kind of bugs, you can run your code with [Address Sanitizer](https://clang.llvm.org/docs/AddressSanitizer.html)
+and [Undefined Behavior Sanitizer](https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html).
+This is mostly done automagically by various CI systems for each PR, but you may
+want to do it locally as well. The process slightly varies depending on the
+compiler you want to use and which part of the test suite you want to run.
+
+## gcc
+gcc compiles in sanitizer libraries dynamically by default, so you need to get
+the shared libraries first - on Fedora these are shipped as a separate packages
+(`libasan` for Address Sanitizer and `libubsan` for Undefined Behavior Sanitizer).
+
+The compilation itself is then a matter of simply adding `-Db_sanitize=address,undefined`
+to `meson`. That's it - following executions of `meson test` and integrations tests
+under `test/` subdirectory will run with sanitizers enabled. However, to get
+truly useful results, you should tweak the runtime configuration of respective
+sanitizers; e.g. in systemd we set the following environment variables:
+
+```bash
+ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
+UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+```
+## clang
+In case of clang things are somewhat different - the sanitizer libraries are
+compiled in statically by default. This is not an issue if you plan to run
+only the unit tests, but for integration tests you'll need to convince clang
+to use the dynamic versions of sanitizer libraries.
+
+First of all, pass `-shared-libsan` to both `clang` and `clang++`:
+
+```bash
+CFLAGS=-shared-libasan
+CXXFLAGS=-shared-libasan
+```
+
+The `CXXFLAGS` are necessary for `src/libsystemd/sd-bus/test-bus-vtable-cc.c`. Compilation
+is then the same as in case of gcc, simply add `-Db_sanitize=address,undefined`
+to the `meson` call and use the same environment variables for runtime configuration.
+
+```bash
+ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
+UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1
+```
+
+After this, you'll probably notice that all compiled binaries complain about
+missing `libclang_rt.asan*` library. To fix this, you have to install clang's
+runtime libraries, usually shipped in the `compiler-rt` package. As these libraries
+are installed in a non-standard location (non-standard for `ldconfig`), you'll
+need to manually direct binaries to the respective runtime libraries.
+
+```
+# Optionally locate the respective runtime DSO
+$ ldd build/systemd | grep libclang_rt.asan
+ libclang_rt.asan-x86_64.so => not found
+ libclang_rt.asan-x86_64.so => not found
+$ find /usr/lib* /usr/local/lib* -type f -name libclang_rt.asan-x86_64.so 2>/dev/null
+/usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so
+
+# Set the LD_LIBRARY_PATH accordingly
+export LD_LIBRARY_PATH=/usr/lib64/clang/7.0.1/lib/
+
+# If the path is correct, the "not found" message should change to an actual path
+$ ldd build/systemd | grep libclang_rt.asan
+ libclang_rt.asan-x86_64.so => /usr/lib64/clang/7.0.1/lib/libclang_rt.asan-x86_64.so (0x00007fa9752fc000)
+```
+
+This should help binaries to correctly find necessary sanitizer DSOs.
+
+Also, to make the reports useful, `llvm-symbolizer` tool is required (usually
+part of the `llvm` package).
+
+## Background notes
+The reason why you need to force dynamic linking in case of `clang` is that some
+applications make use of `libsystemd`, which is compiled with sanitizers as well.
+However, if a *standard* (uninstrumented) application loads an instrumented library,
+it will immediately fail due to unresolved symbols. To fix/workaround this, you
+need to pre-load the ASan DSO using `LD_PRELOAD=/path/to/asan/dso`, which will
+make things work as expected in most cases. This will, obviously, not work with
+statically linked sanitizer libraries.
+
+These shenanigans are performed automatically when running the integration test
+suite (i.e. `test/TEST-??-*`) and are located in `test/test-functions` (mainly,
+but not only, in the `create_asan_wrapper` function).