4

I would like that a shared library is always loaded at the same address on Android 4.0.3.

I can't seem to disable the ASLR using:

echo 0 > /proc/sys/kernel/randomize_va_space

Running

cat /proc/sys/kernel/randomize_va_space

indeed shows 0, but after starting the application the shared library is always (still) loaded at a different address.

EDIT:

Above behavior is seen when starting an activity that loads a shared object using command

am start -n <activity>

OTOH, when trying with a small native process written in C, the same shared library gets loaded to the same addresses when ASLR is disabled either with

echo 0 > /proc/sys/kernel/randomize_va_space

or

sysctl -w kernel.randomize_va_space=0

I've compiled the application using android-ndk-r7c toolchain arm-linux-androideabi-4.4.3 without any special compiler switches (e.g. -fPIE or -pie).

I've also tried something like described here, but the shared library still gets loaded at different addresses - I guess that per-process ASLR can not be disabled on Android.

I have not managed to cross-compile the setarch.c from util-linux due to missing SYS_personality.

EDIT2:

Further investigation resulted in a partial success. This is what I've done and the result is that the application started via "am start -n " loads shared library on mostly two different addresses:

  1. set the ASLR to disabled state using one of the methods,
  2. kill the "/system/bin/servicemanager" process (kill -9 PID) - this should bring down the zygote and complete UI, too,
  3. wait for the servicemanager, zygote and UI to restart - init.rc handles this,
  4. try to start/kill/start my application

After 20 + start & kill sequences my application always loads shared library on one or another memory address. How come? Have no idea!

Nevertheless this should help debugging the shared library greatly since the shared library is usually loaded on one address several time in a row and then on another address next couple of times and bask to first address..

5
  • Have you tried: sysctl -w kernel.randomize_va_space=0 ?
    – perror
    Feb 12, 2014 at 18:53
  • @perror: this is effectively the same as the echo line given in the question.
    – 0xC0000022L
    Feb 12, 2014 at 20:33
  • Not exactly, because the ASLR is disabled in a permanent manner. But, I agree. Effects should be the same.
    – perror
    Feb 12, 2014 at 20:37
  • @perror Yes I have. The effect is the same - cat /proc/sys/kernel/randomize_va_space shows and sysctl kernel.randomize_va_space show value 0, but the shared library is still loaded at different address. Feb 12, 2014 at 21:24
  • Jon Oberheide's A look at ASLR in Android Ice Cream Sandwich 4.0 might be helpful.
    – jww
    Jun 14, 2014 at 22:50

1 Answer 1

3

In fact, the ASLR is architecture dependent. I didn't managed to get the sources from Android, but I took a look at the various ARM implementation of the Linux kernel.

In ARM64, I found a perfectly valid implementation of the ASLR (in arch/arm64/kernel/process.c):

unsigned long arch_align_stack(unsigned long sp)
{
  if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
     sp -= get_random_int() & ~PAGE_MASK;
  return sp & ~0xf;
}

static unsigned long randomize_base(unsigned long base)
{
  unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1;
  return randomize_range(base, range_end, 0) ? : base;
}

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
  return randomize_base(mm->brk);
}

unsigned long randomize_et_dyn(unsigned long base)
{
  return randomize_base(base);
}

But, looking at arch/arm/kernel/process.c, the ASLR seems to not trigger the ASLR at all, except for:

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
   unsigned long range_end = mm->brk + 0x02000000;
   return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}

This ARM version of Linux doesn't seems to take into account the trigger of randomize_va_space to control ASLR.

In place of this, the only way to control it seems to be the process personality flags (which are process-wide and NOT system-wide):

    $> setarch `uname -m` -R elf_exec

I will probably be able to say more if I can get the hand on the Android kernel source code.

2
  • 1
    On my device uname -m returns "armv7l" and the busybox v1.21.0 based setarch I have onboard recognizes only linux32 and linux64 personalities. Also it does not even recognize the -R switch AFAIK. I'll try and use the real setarch, not busybox based to see if it helps. I have kernel version 3.0.8. Thanks for the effort on researching! Feb 12, 2014 at 22:57
  • 1
    @perror - "I didn't managed to get the sources from Android..." - for Android, see fs/binfmt_elf.c. Also see A look at ASLR in Android Ice Cream Sandwich 4.0.
    – jww
    Jun 14, 2014 at 22:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.