2 #===- lib/asan/scripts/asan_device_setup -----------------------------------===#
4 # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 # See https://llvm.org/LICENSE.txt for license information.
6 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 # Prepare Android device to run ASan applications.
10 #===------------------------------------------------------------------------===#
14 HERE
="$(cd "$
(dirname "$0")" && pwd)"
23 echo "usage: $0 [--revert] [--device device-id] [--lib path] [--extra-options options]"
24 echo " --revert: Uninstall ASan from the device."
25 echo " --lib: Path to ASan runtime library."
26 echo " --extra-options: Extra ASAN_OPTIONS."
27 echo " --device: Install to the given device. Use 'adb devices' to find"
29 echo " --use-su: Use 'su -c' prefix for every adb command instead of using"
30 echo " 'adb root' once."
36 if [ $use_su -eq 0 ]; then
39 local FILENAME
=$
(basename $1)
40 $ADB push
"$1" "/data/local/tmp/$FILENAME"
41 $ADB shell su
-c "rm \\\"$2/$FILENAME\\\"" >&/dev
/null
42 $ADB shell su
-c "cat \\\"/data/local/tmp/$FILENAME\\\" > \\\"$2/$FILENAME\\\""
43 $ADB shell su
-c "rm \\\"/data/local/tmp/$FILENAME\\\""
47 function adb_remount
{
48 if [ $use_su -eq 0 ]; then
51 local STORAGE
=`$ADB shell mount | grep /system | cut -d ' ' -f1`
52 if [ "$STORAGE" != "" ]; then
53 echo Remounting
$STORAGE at /system
54 $ADB shell su
-c "mount -o rw,remount $STORAGE /system"
56 echo Failed to get storage device name
for "/system" mount point
62 if [ $use_su -eq 0 ]; then
70 if [ $use_su -eq 0 ]; then
75 function adb_wait_for_device
{
80 if [ $use_su -eq 0 ]; then
83 local FILENAME
=$
(basename $1)
84 $ADB shell
rm "/data/local/tmp/$FILENAME" >&/dev
/null
85 $ADB shell su
-c "[ -f \\\"$1\\\" ] && cat \\\"$1\\\" > \\\"/data/local/tmp/$FILENAME\\\" && chown root.shell \\\"/data/local/tmp/$FILENAME\\\" && chmod 755 \\\"/data/local/tmp/$FILENAME\\\"" &&
86 $ADB pull
"/data/local/tmp/$FILENAME" "$2" >&/dev
/null
&& $ADB shell
"rm \"/data/local/tmp/$FILENAME\""
90 function get_device_arch
{ # OUT OUT64
93 local _ABI
=$
(adb_shell getprop ro.product.cpu.abi
)
96 if [[ $_ABI == x86
* ]]; then
98 elif [[ $_ABI == armeabi
* ]]; then
100 elif [[ $_ABI == arm64-v8a
* ]]; then
104 echo "Unrecognized device ABI: $_ABI"
107 eval $_outvar=\
$_ARCH
108 eval $_outvar64=\
$_ARCH64
111 while [[ $# > 0 ]]; do
118 if [[ $# == 0 ]]; then
119 echo "--extra-options requires an argument."
126 if [[ $# == 0 ]]; then
127 echo "--lib requires an argument."
134 if [[ $# == 0 ]]; then
135 echo "--device requires an argument."
151 if [[ x
$device != x
]]; then
152 ADB
="$ADB -s $device"
155 if [ $use_su -eq 1 ]; then
156 # Test if 'su' is present on the device
157 SU_TEST_OUT
=`$ADB shell su -c "echo foo" 2>&1 | sed 's/\r$//'`
158 if [ $?
!= 0 -o "$SU_TEST_OUT" != "foo" ]; then
159 echo "ERROR: Cannot use 'su -c':"
160 echo "$ adb shell su -c \"echo foo\""
162 echo "Check that 'su' binary is correctly installed on the device or omit"
163 echo " --use-su flag"
168 echo '>> Remounting /system rw'
175 get_device_arch ARCH ARCH64
176 echo "Target architecture: $ARCH"
177 ASAN_RT
="libclang_rt.asan-$ARCH-android.so"
178 if [[ -n $ARCH64 ]]; then
179 echo "Target architecture: $ARCH64"
180 ASAN_RT64
="libclang_rt.asan-$ARCH64-android.so"
183 RELEASE
=$
(adb_shell getprop ro.build.version.release
)
185 if echo "$RELEASE" |
grep '^4\.' >&/dev
/null
; then
189 if echo "$RELEASE" |
grep '^8\.0\.' >&/dev
/null
; then
190 # 8.0.x is for Android O
194 if [[ x
$revert == xyes
]]; then
195 echo '>> Uninstalling ASan'
197 if ! adb_shell
ls -l /system
/bin
/app_process |
grep -o '\->.*app_process' >&/dev
/null
; then
198 echo '>> Pre-L device detected.'
199 adb_shell
mv /system
/bin
/app_process.real
/system
/bin
/app_process
200 adb_shell
rm /system
/bin
/asanwrapper
201 elif ! adb_shell
ls -l /system
/bin
/app_process64.real |
grep -o 'No such file or directory' >&/dev
/null
; then
202 # 64-bit installation.
203 adb_shell
mv /system
/bin
/app_process32.real
/system
/bin
/app_process32
204 adb_shell
mv /system
/bin
/app_process64.real
/system
/bin
/app_process64
205 adb_shell
rm /system
/bin
/asanwrapper
206 adb_shell
rm /system
/bin
/asanwrapper64
208 # 32-bit installation.
209 adb_shell
rm /system
/bin
/app_process.wrap
210 adb_shell
rm /system
/bin
/asanwrapper
211 adb_shell
rm /system
/bin
/app_process
212 adb_shell
ln -s /system
/bin
/app_process32
/system
/bin
/app_process
215 if [[ ANDROID_O
-eq 1 ]]; then
216 adb_shell
mv /system
/etc
/ld.config.txt.saved
/system
/etc
/ld.config.txt
219 echo '>> Restarting shell'
223 # Remove the library on the last step to give a chance to the 'su' binary to
224 # be executed without problem.
225 adb_shell
rm /system
/lib
/$ASAN_RT
231 if [[ -d "$lib" ]]; then
233 elif [[ -f "$lib" && "$lib" == *"$ASAN_RT" ]]; then
234 ASAN_RT_PATH
=$
(dirname "$lib")
235 elif [[ -f "$HERE/$ASAN_RT" ]]; then
237 elif [[ $
(basename "$HERE") == "bin" ]]; then
238 # We could be in the toolchain's base directory.
239 # Consider ../lib, ../lib/asan, ../lib/linux,
240 # ../lib/clang/$VERSION/lib/linux, and ../lib64/clang/$VERSION/lib/linux.
241 P
=$
(ls "$HERE"/..
/lib
/"$ASAN_RT" \
242 "$HERE"/..
/lib
/asan
/"$ASAN_RT" \
243 "$HERE"/..
/lib
/linux
/"$ASAN_RT" \
244 "$HERE"/..
/lib
/clang
/*/lib
/linux
/"$ASAN_RT" \
245 "$HERE"/..
/lib64
/clang
/*/lib
/linux
/"$ASAN_RT" 2>/dev
/null |
sort |
tail -1)
246 if [[ -n "$P" ]]; then
247 ASAN_RT_PATH
="$(dirname "$P")"
251 if [[ -z "$ASAN_RT_PATH" ||
! -f "$ASAN_RT_PATH/$ASAN_RT" ]]; then
252 echo ">> ASan runtime library not found"
256 if [[ -n "$ASAN_RT64" ]]; then
257 if [[ -z "$ASAN_RT_PATH" ||
! -f "$ASAN_RT_PATH/$ASAN_RT64" ]]; then
258 echo ">> ASan runtime library not found"
263 TMPDIRBASE
=$
(mktemp
-d)
264 TMPDIROLD
="$TMPDIRBASE/old"
265 TMPDIR
="$TMPDIRBASE/new"
268 if ! adb_shell
ls -l /system
/bin
/app_process |
grep -o '\->.*app_process' >&/dev
/null
; then
270 if adb_pull
/system
/bin
/app_process.real
/dev
/null
>&/dev
/null
; then
271 echo '>> Old-style ASan installation detected. Reverting.'
272 adb_shell
mv /system
/bin
/app_process.real
/system
/bin
/app_process
275 echo '>> Pre-L device detected. Setting up app_process symlink.'
276 adb_shell
mv /system
/bin
/app_process
/system
/bin
/app_process32
277 adb_shell
ln -s /system
/bin
/app_process32
/system
/bin
/app_process
280 echo '>> Copying files from the device'
281 if [[ -n "$ASAN_RT64" ]]; then
282 adb_pull
/system
/lib
/"$ASAN_RT" "$TMPDIROLD" || true
283 adb_pull
/system
/lib64
/"$ASAN_RT64" "$TMPDIROLD" || true
284 adb_pull
/system
/bin
/app_process32
"$TMPDIROLD" || true
285 adb_pull
/system
/bin
/app_process32.real
"$TMPDIROLD" || true
286 adb_pull
/system
/bin
/app_process64
"$TMPDIROLD" || true
287 adb_pull
/system
/bin
/app_process64.real
"$TMPDIROLD" || true
288 adb_pull
/system
/bin
/asanwrapper
"$TMPDIROLD" || true
289 adb_pull
/system
/bin
/asanwrapper64
"$TMPDIROLD" || true
291 adb_pull
/system
/lib
/"$ASAN_RT" "$TMPDIROLD" || true
292 adb_pull
/system
/bin
/app_process32
"$TMPDIROLD" || true
293 adb_pull
/system
/bin
/app_process.wrap
"$TMPDIROLD" || true
294 adb_pull
/system
/bin
/asanwrapper
"$TMPDIROLD" || true
296 cp -r "$TMPDIROLD" "$TMPDIR"
298 if [[ -f "$TMPDIR/app_process.wrap" ||
-f "$TMPDIR/app_process64.real" ]]; then
299 echo ">> Previous installation detected"
301 echo ">> New installation"
304 echo '>> Generating wrappers'
306 cp "$ASAN_RT_PATH/$ASAN_RT" "$TMPDIR/"
307 if [[ -n "$ASAN_RT64" ]]; then
308 cp "$ASAN_RT_PATH/$ASAN_RT64" "$TMPDIR/"
311 ASAN_OPTIONS
=start_deactivated
=1
313 # The name of a symlink to libclang_rt.asan-$ARCH-android.so used in LD_PRELOAD.
314 # The idea is to have the same name in lib and lib64 to keep it from falling
315 # apart when a 64-bit process spawns a 32-bit one, inheriting the environment.
316 ASAN_RT_SYMLINK
=symlink-to-libclang_rt.asan
318 function generate_zygote_wrapper
{ # from, to
321 if [[ PRE_L
-eq 0 ]]; then
322 # LD_PRELOAD parsing is broken in N if it starts with ":". Luckily, it is
323 # unset in the system environment since L.
324 local _ld_preload
=$ASAN_RT_SYMLINK
326 local _ld_preload
=\
$LD_PRELOAD:$ASAN_RT_SYMLINK
328 cat <<EOF >"$TMPDIR/$_from"
329 #!/system/bin/sh-from-zygote
330 ASAN_OPTIONS=$ASAN_OPTIONS \\
331 ASAN_ACTIVATION_OPTIONS=include_if_exists=/data/local/tmp/asan.options.%b \\
332 LD_PRELOAD=$_ld_preload \\
338 # On Android-L not allowing user segv handler breaks some applications.
339 # Since ~May 2017 this is the default setting; included for compatibility with
340 # older library versions.
341 if [[ PRE_L
-eq 0 ]]; then
342 ASAN_OPTIONS
="$ASAN_OPTIONS,allow_user_segv_handler=1"
345 if [[ x
$extra_options != x
]] ; then
346 ASAN_OPTIONS
="$ASAN_OPTIONS,$extra_options"
350 if [[ -f "$TMPDIR/app_process64" ]]; then
352 if [[ ! -f "$TMPDIR/app_process64.real" ]]; then
354 mv "$TMPDIR/app_process32" "$TMPDIR/app_process32.real"
355 mv "$TMPDIR/app_process64" "$TMPDIR/app_process64.real"
357 generate_zygote_wrapper
"app_process32" "/system/bin/app_process32.real"
358 generate_zygote_wrapper
"app_process64" "/system/bin/app_process64.real"
361 generate_zygote_wrapper
"app_process.wrap" "/system/bin/app_process32"
364 # General command-line tool wrapper (use for anything that's not started as
366 cat <<EOF >"$TMPDIR/asanwrapper"
368 LD_PRELOAD=$ASAN_RT_SYMLINK \\
373 if [[ -n "$ASAN_RT64" ]]; then
374 cat <<EOF >"$TMPDIR/asanwrapper64"
376 LD_PRELOAD=$ASAN_RT_SYMLINK \\
382 function install { # from, to, chmod, chcon
387 local _basename
="$(basename "$_from")"
388 echo "Installing $_to/$_basename $_mode $_context"
389 adb_push
"$_from" "$_to/$_basename"
390 adb_shell chown root.shell
"$_to/$_basename"
391 if [[ -n "$_mode" ]]; then
392 adb_shell
chmod "$_mode" "$_to/$_basename"
394 if [[ -n "$_context" ]]; then
395 adb_shell chcon
"$_context" "$_to/$_basename"
399 if ! ( cd "$TMPDIRBASE" && diff -qr old
/ new
/ ) ; then
400 # Make SELinux happy by keeping app_process wrapper and the shell
401 # it runs on in zygote domain.
403 if adb_shell getenforce |
grep Enforcing
>/dev
/null
; then
404 # Sometimes shell is not allowed to change file contexts.
405 # Temporarily switch to permissive.
407 adb_shell setenforce
0
410 if [[ PRE_L
-eq 1 ]]; then
411 CTX
=u
:object_r
:system_file
:s0
413 CTX
=u
:object_r
:zygote_exec
:s0
416 echo '>> Pushing files to the device'
418 if [[ -n "$ASAN_RT64" ]]; then
419 install "$TMPDIR/$ASAN_RT" /system
/lib
644
420 install "$TMPDIR/$ASAN_RT64" /system
/lib64
644
421 install "$TMPDIR/app_process32" /system
/bin
755 $CTX
422 install "$TMPDIR/app_process32.real" /system
/bin
755 $CTX
423 install "$TMPDIR/app_process64" /system
/bin
755 $CTX
424 install "$TMPDIR/app_process64.real" /system
/bin
755 $CTX
425 install "$TMPDIR/asanwrapper" /system
/bin
755
426 install "$TMPDIR/asanwrapper64" /system
/bin
755
428 adb_shell
rm -f /system
/lib
/$ASAN_RT_SYMLINK
429 adb_shell
ln -s $ASAN_RT /system
/lib
/$ASAN_RT_SYMLINK
430 adb_shell
rm -f /system
/lib64
/$ASAN_RT_SYMLINK
431 adb_shell
ln -s $ASAN_RT64 /system
/lib64
/$ASAN_RT_SYMLINK
433 install "$TMPDIR/$ASAN_RT" /system
/lib
644
434 install "$TMPDIR/app_process32" /system
/bin
755 $CTX
435 install "$TMPDIR/app_process.wrap" /system
/bin
755 $CTX
436 install "$TMPDIR/asanwrapper" /system
/bin
755 $CTX
438 adb_shell
rm -f /system
/lib
/$ASAN_RT_SYMLINK
439 adb_shell
ln -s $ASAN_RT /system
/lib
/$ASAN_RT_SYMLINK
441 adb_shell
rm /system
/bin
/app_process
442 adb_shell
ln -s /system
/bin
/app_process.wrap
/system
/bin
/app_process
445 adb_shell
cp /system
/bin
/sh
/system
/bin
/sh-from-zygote
446 adb_shell chcon
$CTX /system
/bin
/sh-from-zygote
448 if [[ ANDROID_O
-eq 1 ]]; then
449 # For Android O, the linker namespace is temporarily disabled.
450 adb_shell
mv /system
/etc
/ld.config.txt
/system
/etc
/ld.config.txt.saved
453 if [ $ENFORCING == 1 ]; then
454 adb_shell setenforce
1
457 echo '>> Restarting shell (asynchronous)'
461 echo '>> Please wait until the device restarts'
463 echo '>> Device is up to date'