Skip to content

Segmentation fault due to chroot in Android 14 #5

Description

@NICUP14

On some devices running Android 14 or newer the environment fails to initialize due to a segmentation fault raised by the chroot command with error code SIGCHLD.

Offender:

$BUSYBOX chroot "$DEBDROIDMGR_ENV" /bin/su - -c "sh /debdroid/bin/debinit && $DEBDROIDMGR_EXEC"

Output:

/sdcard/debdroid/debdroid_mgr.sh: Starting environment: "/data/local/debdroid/mnt"
Attempting image repair...
/sdcard/debdroid/img/debian.img: 12795/245760 files (12.2% non-contiguous), 106851/976562 blocks
/sdcard/debdroid/debdroid_mgr.sh: Missing overlay support, falling back to bind-mount for /dev.
/sdcard/debdroid/debdroid_mgr.sh: Overlay failed, falling back to bind-mount for /dev.
/sdcard/debdroid/debdroid_mgr.sh: DNS resolution failed, falling back to nameserver 1.1.1.1
/sdcard/debdroid/debdroid_mgr.sh: Running chroot command: "/bin/su"
Segmentation fault
/sdcard/debdroid/debdroid_mgr.sh: Stopping environment: "/data/local/debdroid/mnt"

Strace:

/sdcard/debdroid/debdroid_mgr.sh: Running chroot command: "/bin/su"
Segmentation fault
/sdcard/debdroid/debdroid_mgr.sh: Stopping environment: "/data/local/debdroid/mnt"
)               = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=24109, si_uid=0, si_status=0, si_utime=0, si_stime=3} ---
getrusage(RUSAGE_CHILDREN, {ru_utime={tv_sec=0, tv_usec=0}, ru_stime={tv_sec=0, tv_usec=0}, ru_maxrss=0, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=0, ru_majflt=0, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=0, ru_nivcsw=0}) = 0
wait4(-1, [{WIFEXITED(s) && WEXITSTATUS(s) == 0}], WNOHANG|WSTOPPED|WCONTINUED, NULL) = 24109
getrusage(RUSAGE_CHILDREN, {ru_utime={tv_sec=0, tv_usec=490000}, ru_stime={tv_sec=0, tv_usec=330000}, ru_maxrss=3076, ru_ixrss=0, ru_idrss=0, ru_isrss=0, ru_minflt=19314, ru_majflt=2, ru_nswap=0, ru_inblock=0, ru_oublock=0, ru_msgsnd=0, ru_msgrcv=0, ru_nsignals=0, ru_nvcsw=7171, ru_nivcsw=124}) = 0
wait4(-1, 0x7ffe9b9bec, WNOHANG|WSTOPPED|WCONTINUED, NULL) = -1 ECHILD (No child processes)
rt_sigreturn({mask=[CHLD RTMIN]})       = -1 EINTR (Interrupted system call)
rt_sigprocmask(SIG_SETMASK, [RTMIN], NULL, 8) = 0
madvise(0x7488a6e000, 4096, MADV_DONTNEED) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD RTMIN], [RTMIN], 8) = 0
rt_sigprocmask(SIG_SETMASK, [RTMIN], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD RTMIN], NULL, 8) = 0
madvise(0x7488a5a000, 4096, MADV_DONTNEED) = 0
madvise(0x7488a24000, 4096, MADV_DONTNEED) = 0
fcntl(3, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(4, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(5, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(6, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(7, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(8, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(9, F_GETFD)                       = -1 EBADF (Bad file descriptor)
fcntl(10, F_GETFD)                      = 0x1 (flags FD_CLOEXEC)
close(10)                               = 0
fcntl(11, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(12, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(13, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(14, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(15, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(16, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(17, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(18, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(19, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(20, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(21, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(22, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(23, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(24, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(25, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(26, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(27, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(28, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(29, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(30, F_GETFD)                      = -1 EBADF (Bad file descriptor)
fcntl(31, F_GETFD)                      = -1 EBADF (Bad file descriptor)
close(2)                                = 0
close(1)                                = 0
close(0)                                = 0
mprotect(0x748b8c7000, 4096, PROT_READ|PROT_WRITE) = 0

Notes:

  • This is most probably caused by a linker restriction introduced in newer versions of Android.
  • Commands can be manually executed by directly invoking the linker. (ex: /lib/ld-linux-aarch64.so.1 /bin/ls)

Proposed Solution:

The proposed solution involves patching the execve() system call to manually prepend the linker for every executed command. The fix is currently under development.

Tested on a Samsung Tab2 gts210velte device running LineageOS 21 rooted with Magisk. (Android 14)

- NICUP14

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions