Development Asan

Building Packages With ASAN

Many times CVEs and other security-related bugs that are reported make use of AddressSanitizer in order to identify the defective behavior. Frequently, the reporter of a bug or issue will provide proof of concept or working example that relies on the program or library having been build with AddressSanitizer support.

This article describes what is necessary for building a package with AddressSanitizer support.

Passing Appropriate Flags

Generally, what is necessary for AddressSanitizer is to pass the appropriate compiler and linker flags to the build.

Many Debian packages use dpkg-buildflags and so the build can be adjusted without modifying debian/rules by setting environment variables like this:

export DEB_CFLAGS_APPEND=-fsanitize=address
export DEB_CPPFLAGS_APPEND=-fsanitize=address
export DEB_CXXFLAGS_APPEND=-fsanitize=address
export DEB_LDFLAGS_APPEND='-fsanitize=address -static-libasan'

The point of the -static-libasan flag is to have GCC statically link ASAN without also statically linking everything else. Adding that flag makes installation of the resulting packages easier as they will not depend on the libasan shared library. That seems to cause issues with C++ programs though (“Your application is linked against incompatible ASan runtimes.”).

There are instances, depending on the build system, particular compiler, compiler version, and perhaps other factors, where the -static-libasan flag might lead to linking failures. The failures in that case are of the form undefined reference to __asan_[…]. If that happens, one possible (hacky?) way to address the failure is by modifying the LDFLAGS:

export DEB_LDFLAGS_APPEND='-fsanitize=address -lasan -ldl'

There are other flags, like -fsanitize=thread, -fsanitize=leak, -fsanitize=undefined, along with their corresponding -static-* flags which may be useful depending on the nature of the bug report or vulnerability, for instance with ASAN+UBSAN:

export DEB_CFLAGS_APPEND='-fsanitize=address,undefined'
export DEB_CPPFLAGS_APPEND='-fsanitize=address,undefined'
export DEB_CXXFLAGS_APPEND='-fsanitize=address,undefined'
export DEB_LDFLAGS_APPEND='-fsanitize=address,undefined -static-libasan -static-libubsan'

libtool may filter the LDFLAGS; you may need a patch

Beware that FORTIFY is not officially supported, see FAQ

This approach works for cowbuilder, pbuilder, and other build chroot-type environments (including those invoked by git-buildpackage, for example) which will pass the environment variables through.

If the package being built does not properly support dpkg-buildflags or if a build method is being used which does not properly handle the environment, then it may be necessary temporarily modify debian/rules in order to insert the necessary flags at the appropriate locations. Depending on the package being updated and whether the source is available in Git or come other VCS, it might make sense to create a branch for the temporary modifications to the build.

It is also a good idea to leave the changelog in a state that will prevent accidental upload of the package built with ASAN. This can be accomplished by starting a new changelog entry and leaving the suite set to UNRELEASED.

Alternatively, valgrind may be used to assess the presence of an invalid memory access before/after patching.

Further Readings

Some links which might provide additional information: