Android - Address Sanitizer for Native applications

   Address Sanitizer's support for Android works quite well that the application isn't slowed down to a drastic extent that it isn't usable anymore. The latest NDK ( Revision 10d ) offers easy use to enable address sanitizer for applications. It doesn't work in Android L and isn't supported for 64bit ABIs.

   It needs the following compile time options to be enabled in Android.mk,

         LOCAL_CFLAGS    := -fsanitize=address -fno-omit-frame-pointer
         LOCAL_LDFLAGS   := -fsanitize=address
         LOCAL_ARM_MODE := arm

and following in Application.mk to use clang 3.5

         NDK_TOOLCHAIN_VERSION=clang3.5

   Address Sanitizer basically instruments the code for run time analysis and doesn't offer static analysis. This works for malloc, realloc and free. new and delete is supported only when c++ stdlib is linked dynamically and not statically in the binary.

        APP_STL := gnustl_shared

From here on, the binary can be compiled with ndk-build and can be used with the application. In addition, the android device needs to be setup and NDK offers a script (asan_device_setup) which works fine on a linux machine. For mac (running Yosemite), it just needs a minor change,

   + TMPDIRBASE=$(mktemp -d -t template)
    - TMPDIRBASE=$(mktemp -d)

   The script works only on a rooted phone as the system partition needs to be remounted for write access. This script basically pushes app_process.wrap and asanwrapper into /system/bin and libclang_rt.asan-arm-android.so into /system/lib and restarts the device. Script needs the NDK path having libclang_rt.asan-arm-android.so.

./toolchains/llvm-3.5/prebuilt/darwin-x86_64/bin/asan_device_setup --lib ./toolchains/llvm-3.5/prebuilt/darwin-x86_64/lib/clang/3.5/lib/linux

   app_process.wrap is just a script that sets sanitizer options, sets libclang_rt.asan-arm-android.so to be preloaded and launch the usual app_process.

#!/system/bin/sh-from-zygote
ASAN_OPTIONS=start_deactivated=1,alloc_dealloc_mismatch=0 \
LD_PRELOAD=$LD_PRELOAD:libclang_rt.asan-arm-android.so \
exec /system/bin/app_process32 $@

   The Sanitizer's runtime library (libclang_rt.asan-arm-android.so) is preloaded to ensure it gets more preference during symbol lookup and this is how Address Sanitizer is able to intercept libc calls like malloc and free. Besides, the interception is delayed to ensure that it doesn't kick in for Zygote instead works only for the application when Zygote forks a process to start the application. Anyways, the device is ready once the script finishes. A sample run has the following output,

adbd is already running as root
remount succeeded
Target architecture: arm
>> Copying files from the device
remote object '/system/bin/app_process.wrap' does not exist
remote object '/system/bin/asanwrapper' does not exist
remote object '/system/lib/libclang_rt.asan-arm-android.so' does not exist
>> New installation
>> Generating wrappers
Only in new/: app_process.wrap
Only in new/: asanwrapper
Only in new/: libclang_rt.asan-arm-android.so
>> Pushing files to the device
4210 KB/s (1638592 bytes in 0.380s)
81 KB/s (181 bytes in 0.002s)
30 KB/s (71 bytes in 0.002s)
>> Restarting shell (asynchronous)
>> Please wait until the device restarts

The script also uninstalls the wrapped setup via and its safe to use on a daily driver phone too.

./toolchains/llvm-3.5/prebuilt/darwin-x86_64/bin/asan_device_setup --revert

>> Remounting /system rw
restarting adbd as root
remount succeeded
Target architecture: arm
>> Uninstalling ASan
>> Restarting shell
>> Done

The final step is to set a property,

adb shell setprop wrap.com.sample.testapp "logwrapper asanwrapper"

  This ensures that logwrapper is the parent process of the application process and it basically redirects asanwrapper logs to logical. There would be a noticeable delay during application launch but once launched the performance isn't bad at all. And the application is ready to be sanitized. Its up to developers to ensure that all use cases are executed and this is perhaps why it is a good idea to enable ASAN during early development cycle.

No comments: