VOOZH about

URL: https://dev.to/opassoca/running-native-glibc-debian-binaries-on-android-15-without-proot-1hmo

โ‡ฑ Running Native glibc (Debian) Binaries on Android 15 Without PRoot - DEV Community


๐Ÿ”ง TL;DR: Android 15 broke PRoot with stricter seccomp filters. After ~10 hours of debugging, I found a working solution using patchelf + LD_PRELOAD= to run native Linux (Debian/glibc) binaries directly on Termux!


The Problem

Android 15 significantly tightened its seccomp security filters. Running any Debian/glibc binary via proot-distro now fails with:

Bad system call (SIGSYS)
set_robust_list: Function not implemented

โš ๏ธ Important: This isn't a configuration issue. The kernel literally blocks the syscalls that PRoot needs to emulate a Linux environment.

Every guide said "just use PRoot" โ†’ so I spent ~10 hours finding what actually works.


Understanding Seccomp


The Solution โ€” Three Tiers

I developed a three-tier approach depending on your needs:


Root Cause โ€” Why PRoot Fails


Device Information


Prerequisites


Installation Guide

Step 1: Install Debian rootfs

# Install required packages
pkg install proot-distro rsync -y

# Install Debian
proot-distro install debian

# Define paths
ROOTFS="$PREFIX/var/lib/proot-distro/installed-rootfs/debian"
GLIBC="$HOME/glibc-root"

# Install base packages
proot-distro login debian -- bash -c "
 apt-get update &&
 apt-get install -y gcc g++ make python3 bun curl unzip zip ca-certificates
"

๐Ÿ“– What is proot-distro? | What is rsync?


Step 2: Extract rootfs to native location

mkdir -p "$GLIBC"
rsync -a "$ROOTFS/" "$GLIBC/"


Step 3: Fix the dynamic linker

GLIBC="$HOME/glibc-root"
LOADER="$GLIBC/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"

mkdir -p "$GLIBC/lib64"
ln -sf "$LOADER" "$GLIBC/lib64/ld-linux-aarch64.so.1"
ln -sf "$LOADER" "$GLIBC/lib/ld-linux-aarch64.so.1"

๐Ÿ“– Learn about ld-linux.so


Step 4: Mass patchelf โ€” make all binaries self-contained

GLIBC="$HOME/glibc-root"
LOADER="$GLIBC/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"
RPATH="$GLIBC/lib/aarch64-linux-gnu:$GLIBC/usr/lib/aarch64-linux-gnu"
OUT="$PREFIX/bin"

for bin in "$GLIBC/usr/bin/"* "$GLIBC/bin/"*; do
 [[ -f "$bin" && -x "$bin" ]] || continue
 name=$(basename "$bin")-glibc
 cp "$bin" "$OUT/$name"
 patchelf --set-interpreter "$LOADER" \
 --set-rpath "$RPATH" \
 "$OUT/$name" 2>/dev/null || rm -f "$OUT/$name"
done

echo "โœ“ Patched $(ls $OUT/*-glibc 2>/dev/null | wc -l) binaries"

๐Ÿ“– What is patchelf?


Step 5: Fix ownership

su -c "chown -R $(id -u):$(id -g)$HOME/glibc-root"
su -c "find $HOME/glibc-root -type d -exec chmod 755 {} \;"

Step 6: Create the Smart APT wrapper

cat > ~/apt-debian << 'SCRIPT'
#!/data/data/com.termux/files/usr/bin/bash
# apt-debian v3 โ€” installs from Debian and auto-patchelfs

GLIBC="$HOME/glibc-root"
LOADER="$GLIBC/lib/aarch64-linux-gnu/ld-linux-aarch64.so.1"
RPATH="$GLIBC/lib/aarch64-linux-gnu:$GLIBC/usr/lib/aarch64-linux-gnu"

case "$1" in
 install)
 shift
 BEFORE=$(find "$GLIBC/usr/bin" "$GLIBC/bin" -maxdepth 1 -type f -executable 2>/dev/null | sort)
 su -c "cp /system/etc/resolv.conf $GLIBC/etc/resolv.conf 2>/dev/null || \
 echo 'nameserver 8.8.8.8' > $GLIBC/etc/resolv.conf"
 su -c "chroot $GLIBC /usr/bin/apt-get install -y $*"
 AFTER=$(find "$GLIBC/usr/bin" "$GLIBC/bin" -maxdepth 1 -type f -executable 2>/dev/null | sort)
 NEW=$(comm -13 <(echo "$BEFORE") <(echo "$AFTER"))

 for bin in $NEW; do
 name="$(basename $bin)-glibc"
 cp "$bin" "$PREFIX/bin/$name"
 patchelf --set-interpreter "$LOADER" --set-rpath "$RPATH" "$PREFIX/bin/$name" 2>/dev/null
 chmod +x "$PREFIX/bin/$name"
 echo "โœ“ $name available"
 done
 ;;
 update)
 su -c "chroot $GLIBC /usr/bin/apt-get update"
 ;;
 *)
 echo "Usage: apt-debian {install|update} [packages]"
 ;;
esac
SCRIPT

chmod +x ~/apt-debian
mv ~/apt-debian "$PREFIX/bin/apt-debian"

Step 7: Add to PATH

echo 'export PATH="$HOME/.glibc-bin:$PATH"' >> ~/.bashrc
echo 'export GLIBC_ROOT="$HOME/glibc-root"' >> ~/.bashrc
source ~/.bashrc

Testing


Known Limitations


Available Binaries


Understanding ELF and Dynamic Linker


Samsung Firmware Flashing Reference


Summary

Component Technology Reference
Terminal Termux GitHub
ROM ExtremeROM Nexus Android 15
Root KernelSU Exynos 9820
Distribution Debian glibc
Compatibility Layer patchelf ELF modification
Execution Method LD_PRELOAD= bypass Native execution
Device Samsung Galaxy S10e (SM-G970F) - Exynos 9820 ARM64/AArch64

Resources & References

๐Ÿ“ฑ Device & Hardware

Topic Link
Samsung Galaxy S10e (SM-G970F) - Exynos GSMArena
Exynos 9820 Processor Wikipedia
AArch64/ARM64 Architecture Wikipedia
XDA Forum - Galaxy S10e XDA Forums

๐Ÿ”ง Development Tools

Tool Official Site
Termux termux.dev / F-Droid
patchelf GitHub
proot-distro GitHub
F-Droid f-droid.org
Bun bun.sh
GCC gcc.gnu.org
Python python.org
Git git-scm.com
htop htop.dev

๐Ÿ“š Linux Concepts

Topic Link
ELF Format Wikipedia
Seccomp Red Hat Docs
Dynamic Linker man7.org
rsync rsync.samba.org

๐Ÿ” Root & ROM

Project Link
KernelSU kernelsu.org
Magisk topjohnwu.github.io/Magisk
ExtremeROM Nexus GitHub

๐Ÿ”ง Firmware Tools

Tool Link
Odin Wikipedia
Heimdall GitHub
Eros GitHub

Credits


๐Ÿ”ง Developed entirely on Termux โ€” Samsung Galaxy S10e (SM-G970F) ยท Exynos 9820 ยท Android 15 ยท ExtremeXT ยท KernelSU


If this article helped you, give it a ๐Ÿ’š and share with others!

Questions? Feel free to ask in the comments!