MeetBSDCa 2018
Author: Kamil Rytarowski
E-mail: kamil@netbsd.org
Date: October 19th 2018
Place: Intel Santa Clara Campus, California, USA
Kamil Rytarowski (born 1987)
Krakow, Poland
NetBSD user since 6.1.
The NetBSD Foundation member since 2015.
Work areas: kernel, userland, pkgsrc.
Interest: NetBSD on desktop and in particular NetBSD as a workstation.
The current activity in 3rd party software:
Sanitizer is a programming tool that detects computer program bugs such as:
The fundamental four types of sanitizers.
All of them are supported on NetBSD.
Sanitizers.
Valgrind.
The base distribution (HEAD version).
Externally prebuilt standalone toolchain.
Design choices.
Code sanitized with one sanitizer flags shall not be linked with code sanitized with other options.
Implication.
Example of Address Sanitizer (ASan).
1 cc -fsanitize=address main.c -o main
Problems generated by the design of sanitizers: ASLR.
Workaround.
Interceptor is a wrapper for a library function.
Original function in a library.
1 ret_type function(int a0, arg_type1 *a1, arg_type2 *a2);
Inteceptor wraps it (pseudocode).
1 ret_type wrapper_function(int a0, arg_type1 *a1, arg_type2 *a2) {
2 INITIALIZE_INTERCEPTOR(); // sanitizer-specific initialization
3 PRE_READ(a1); // sanitizer-specific pre-read operations
4 PRE_WRITE(a2); // sanitizer-specific pre-write operations
5 ret_type rv = REAL(function)(a0, a1, a2);
6 POST_READ(a1); // sanitizer-specific post-read operations
7 POST_WRITE(a2); // sanitizer-specific post-write operations
8 return rv;
9 }
Sanitizers replace references of the real function() with references of wrapper_function().
Warning: in reality a large amount of interceptors contains various special cases.
Interceptor for strnlen(3).
1 #if SANITIZER_INTERCEPT_STRNLEN
2 INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T maxlen) {
3 void *ctx;
4 COMMON_INTERCEPTOR_ENTER(ctx, strnlen, s, maxlen);
5 SIZE_T length = REAL(strnlen)(s, maxlen);
6 if (common_flags()->intercept_strlen)
7 COMMON_INTERCEPTOR_READ_RANGE(ctx, s, Min(length + 1, maxlen));
8 return length;
9 }
10 #define INIT_STRNLEN COMMON_INTERCEPT_FUNCTION(strnlen)
11 #else
12 #define INIT_STRNLEN
13 #endif
On NetBSD (ELF program file format) interceptors use dynamic loader functionality to install interceptors for routines from a dynamically loaded library.
Sanitizer's runtime inlines a local copy of a certain interceptor into the body of a program, and this symbol is resolved before resolving a symbol from a library.
Solution.
Interceptors can be triggered when code is executing inside a base library and sanitizers usually do not know the context of the surrounding source code
Example (libedit).
1 /* el_resize():
2 * Called from program when terminal is resized
3 */
4 void
5 el_resize(EditLine *el)
6 {
7 int lins, cols;
8 sigset_t oset, nset;
9
10 (void) sigemptyset(&nset);
11 (void) sigaddset(&nset, SIGWINCH);
12 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
13 ...
Memory Sanitizer might report a false positive on an interceptor for sigprocmask(2), because it does not know whether nset is initialized, in case of inlined/not-intercepted version of sigemptyset(3).
Solution.
GNU world.
BSD world.
The GNU vs BSD implications in sanitizers.
Certain symbols require a lot of knowledge about API usage.
1 int
2 mount(const char *type, const char *dir, int flags, void *data,
3 size_t data_len);
The mount(2) call contains per-filesystem structures, e.g.
1 MOUNT_FFS
2 struct ufs_args {
3 char *fspec; /* block special file to mount */
4 };
5
6 MOUNT_MFS
7 struct mfs_args {
8 char *fspec; /* name to export for statfs */
9 struct export_args30 pad; /* unused */
10 caddr_t base; /* base of file system in mem */
11 u_long size; /* size of file system */
12 };
13
14 ... /* over two dozens of filesystems more */
In narrow cases interceptors introduce compatiblity issues between 32 and 64-bit code (such as libkvm - interacting with kernel memory).
In the libkvm case it worked to rebuild the library with a sanitizer natively.
Rebuilding manually all the dependencies of complex C++ applications such as the LLVM Debugger is difficult and laborious.
1 $ ldd /usr/local/bin/lldb
2 /usr/local/bin/lldb:
3 -lpthread.1 => /usr/lib/libpthread.so.1
4 -lc.12 => /usr/lib/libc.so.12
5 -llldb.7 => /usr/local/bin/../lib/liblldb.so.7
6 -lkvm.6 => /usr/lib/libkvm.so.6
7 -ledit.3 => /usr/lib/libedit.so.3
8 -lterminfo.1 => /usr/lib/libterminfo.so.1
9 -lexecinfo.0 => /usr/lib/libexecinfo.so.0
10 -lelf.2 => /usr/lib/libelf.so.2
11 -lgcc_s.1 => /usr/lib/libgcc_s.so.1
12 -lpython2.7.1.0 => /usr/pkg/lib/libpython2.7.so.1.0
13 -lutil.7 => /usr/lib/libutil.so.7
14 -lm.0 => /usr/lib/libm.so.0
15 -lcurses.7 => /usr/lib/libcurses.so.7
16 -lform.6 => /usr/lib/libform.so.6
17 -lpanel.1 => /usr/lib/libpanel.so.1
18 -lxml2.2 => /usr/pkg/lib/libxml2.so.2
19 -lz.1 => /usr/lib/libz.so.1
20 -llzma.2 => /usr/lib/liblzma.so.2
21 -lrt.1 => /usr/lib/librt.so.1
22 -lstdc++.8 => /usr/lib/libstdc++.so.8
Last but not least, if there are already symbols inside an application duplicated with a basesystem - they will conflict with an interceptor.
Workaround.
Summary.
Solution.
Build and use almost all of the userland with a selected sanitizer.
1 ./build.sh \
2 -V MKLLVM=yes \
3 -V MKGCC=no \
4 -V HAVE_LLVM=yes \
5 -V MKSANITIZER=yes \
6 -V USE_SANITIZER="address,undefined" \
7 distribution
Unsanitized exceptions: kernel, loadable kernel modules, ramdisks, static libraries, static programs, base libraries (libc, libm, libpthread, librt).
Functional chroot environment: ASan, UBSan, MSan.
Bootable (& installable) distribution into a functional shell: ASan, UBSan.
As of now the MKSANITIZER flag requires external and patched Clang/LLVM toolchain.
ASan: sh(1), sysinst(8), heimdal krb5, libutil(3), man(1), installboot(8), passwd(8), ...
UBSan: tmux(1), expr(1), ksh(1), ifconfig(8), libc, [gnu]grep(1), gzip(1), [n]awk(1), [n]vi(1), disklabel(8), ...
MSan: sh(1), top(1), ...
... and others that were forgotten to mention.
Table of Contents | t |
---|---|
Exposé | ESC |
Full screen slides | e |
Presenter View | p |
Source Files | s |
Slide Numbers | n |
Toggle screen blanking | b |
Show/hide slide context | c |
Notes | 2 |
Help | h |