Files
DroidDeck/tools/proot/PATCHES.md
Kurt HimebauchandMaxsTechReview 9ed25d8ae5 feat: Flatpak apps and a Flathub store (#77)
* feat: run Flatpak apps through a proot bwrap stand-in and add a Flathub store

* feat: give Flatpak apps the KGSL GPU, the controllers and a CPU LLVM can target

* feat: Flatpak games on the desktop, Store apps on the Desktop page, safer remove

* test: cover the sandbox planner and store helpers; docs: explain Flatpak on DroidDeck

* fix: keep controller focus through Store tabs and app pages; show progress per Flatpak step

* fix: let Chromium, Electron and Firefox Flatpaks start without their own sandboxes

* fix: fetch Flatpak's supporting libraries when the runtime lacks them

* fix: add Flathub without a download, log store commands, keep Electron apps on X11 under gamescope

* feat: import ARM64 AppImages from storage and run them from the Desktop page

* fix: report failed Flatpak installs as failures and deploy runtimes that ship a resolv.conf link

* fix: let Flatpak create its repo where Android denies hard links

* fix: point store commands at the current network's DNS

* fix: keep failed Flatpak extensions non-fatal, give Electron AppImages a bus, X11 and time to relaunch

* docs: AppImage import and what x86 apps would take

* feat: put the Flathub Store and AppImage import behind beta toggles in Setup

---------

Co-authored-by: MaxsTechReview <maxjividen@gmail.com>
2026-09-30 00:35:49 -04:00

6.2 KiB

proot patches carried by the app

Built by tools/proot/build.sh with the NDK on top of termux/proot 4dba3afb (Termux's 5.1.107-70 package, the proot the Linux runtime ships at opt/android-host/proot; every file.c:line site in that binary matches this commit). talloc is linked in statically from Samba's release tarball, so the apk carries one self-contained libproot.so plus libproot-loader.so, and LinuxRuntime prefers them over the runtime's copy.

Ported from WinNative (feature/proot-enhancements, e7af0f24):

  • 0001-tracee-lookup-by-pid.patch - tracees are hashed by pid, so each ptrace stop finds its tracee without walking one list entry per thread, and terminated tracees are swept only after a termination.
  • 0002-canon-resolve-parent-at-once.patch - a clean absolute guest path at least three directories deep under the rootfs binding alone has its parent opened once with O_PATH and taken as canonical when /proc/self/fd names the path proot would build, replacing an lstat per component. The final component of a call that does not follow it is no longer lstated. Extensions still see the parent's host path, and the fast path stays off while the f2fs workaround is active.
  • 0003-clone3-flags-read-guard.patch - a thread created with clone3 keeps the flags it inherited when struct clone_args cannot be read, instead of being tracked as a fork.

Ported from WinNative (main, 53836ca9, "Fix/performance and vac"):

  • 0004-seccomp-filter-by-argument.patch - the seccomp filter traces prctl only for PR_SET_DUMPABLE, setrlimit only for RLIMIT_STACK and prlimit64 only when it sets a new RLIMIT_STACK, the only cases proot acts on; every other call runs without a stop. uname is traced by the core only on x86_64, the one arch it rewrites; kompat still adds it for --kernel-release.
  • 0005-seccomp-skip-unneeded-sysexit.patch - a seccomp stop fetches the registers once and looks the filter flags up by syscall number, instead of a PTRACE_GETEVENTMSG and a second register fetch. The flags table is built from proot's list merged with the enabled extensions' (kompat and fake_id0 here), so it is exactly what the filter reports. wait4/waitpid left to the kernel and accept/accept4 without a sockaddr skip their exit stop, unless an extension replaced the syscall (kompat turning accept4 into accept).
  • 0006-clone3-exit-signal.patch - clone3 flags and exit signal are read as the 64-bit fields of struct clone_args, so a clone3 fork is told apart from a thread when proot decides how the child is traced.
  • 0007-proc-self-thread-group.patch - tracees track their thread group, /proc/self names it instead of the calling thread, and /proc/thread-self resolves to /proc/<tgid>/task/<tid>.
  • 0008-fchmodat2-openat2.patch - fchmodat2 paths are translated (honouring AT_SYMLINK_NOFOLLOW), openat2 answers ENOSYS so callers fall back to the translated openat, and syscall numbers past the end of a table are rejected instead of read.
  • 0009-tracee-relatives-sweep.patch - tracees count their children, so a terminating thread with no children or ptracees no longer walks every tracee; the per-stop memory collector is emptied instead of freed and reallocated.

Added for Flatpak:

  • 0010-new-mount-api-enosys.patch - open_tree, move_mount, fspick and mount_setattr answer ENOSYS. They take paths proot never translated, so libglnx's open_tree(AT_FDCWD, "/") handed Flatpak a descriptor for the host's root and it tried to create directories there (mkdirat(root): Operation not permitted); unsupported, libglnx falls back to openat.

  • 0012-android-hardlink-denial.patch - Android's SELinux policy denies apps hard links, so linkat fails with EACCES and Flatpak could not create its repo (Creating repo: linkat: Permission denied). O_TMPFILE answers EOPNOTSUPP, so libglnx writes a named temporary file and renames it, and a denied link answers EPERM, on which ostree's checkout copies instead. Added by DroidDeck:

  • 0011-kompat-utsname-only.patch - --kernel-release (the guest's DroidDeck hostname) loads kompat, whose filter traps futex, fcntl, epoll_pwait, pselect6, pipe2, eventfd2, socket and more, and which strips AT_SYSINFO_EHDR on every execve, so glibc runs without the vDSO. When the virtual release is not older than the real kernel and the hwcap is left alone, every one of those handlers is a no-op: kompat now traces only uname, sethostname and setdomainname and leaves the auxv as the kernel wrote it. On an SD 8 Gen 2 guest this took a futex ping-pong from 467 to 97 us, epoll_pwait from 60 to 0.8 us and fcntl from 40-107 to 0.4 us, and clock_gettime back to the vDSO.

  • 0012-fake_id0-identity-only.patch - -i uid:gid (for Xwayland's setgid/setuid before it runs xkbcomp) loads fake_id0, whose filter traps every fstat/newfstatat/stat (entry and exit), every sendmsg (all Wayland, X11, Chromium and PulseAudio traffic), socket, getsockopt, the get*id family and the chown/chmod family. When the ids given are the ones proot really has and are not 0, every one of those handlers is a no-op; fake_id0 now traces only the set*id family and the xattr permission fixups, and leaves set-user-ID bits alone on execve (Android mounts the app's data nosuid, so the kernel would not honour them either), which keeps the ids fixed. On an x86_64 host build under the same options: fstat 41.7 -> 1.3 us, sendmsg 18.0 -> 2.5 us.

  • 0013-seccomp-ioctl-by-request-and-kernel-exit-stops.patch - every ioctl stopped on entry and exit, which is every GPU submit and wait. The filter now traces only the requests enter.c and exit.c act on (TCSETSF, the four termios2 requests, FICLONE) and allows the rest at once, and the ioctl block is emitted first (after WinNative 53836ca9, which traces only the termios2 ones). The faccessat2 exit stop (termux 5ba8b95, for glibc's ENOSYS fallback on kernels before 5.8) and the statx one (emulation on kernels before 4.11) are dropped when the running kernel is newer. Host build: ioctl 31.6 -> 0.5 us; stat/statx/faccessat2 about 44 -> 28 us (one stop).