From cb7cfd516e7197d51ff1889bdc402a4e8e796ada Mon Sep 17 00:00:00 2001 From: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> Date: Mon, 9 Nov 2026 09:06:11 -0500 Subject: [PATCH] fix(native): scripts on session mounts outside the rootfs run with the rootfs shell --- tools/nativeguest/hook/exec.c | 4 ++-- tools/nativeguest/hook/paths.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/tools/nativeguest/hook/exec.c b/tools/nativeguest/hook/exec.c index d973ac134..0728620a1 100644 --- a/tools/nativeguest/hook/exec.c +++ b/tools/nativeguest/hook/exec.c @@ -245,7 +245,7 @@ static int ddnatv_execve(const char *filename, char *const argv[], char *const e char resolved_target[PATH_MAX]; // Only intercept binaries/scripts within DDNATV_ROOT - if (g_ddnatv_root[0] != '\0' && strncmp(target, g_ddnatv_root, g_ddnatv_root_len) == 0) { + if ((g_ddnatv_root[0] != '\0' && strncmp(target, g_ddnatv_root, g_ddnatv_root_len) == 0) || is_mapped_guest_path(filename)) { struct exec_probe probe; const char *elf_target = select_exec_target(target, resolved_target, sizeof(resolved_target), &probe); if (probe.is_elf && !probe.is_dynamic) static_elf = elf_target; @@ -798,7 +798,7 @@ static int ddnatv_posix_spawn(pid_t *pid, const char *path, } char *const *orig_ep = envp ? envp : environ; - int in_root = g_ddnatv_root[0] != '\0' && strncmp(target, g_ddnatv_root, g_ddnatv_root_len) == 0; + int in_root = (g_ddnatv_root[0] != '\0' && strncmp(target, g_ddnatv_root, g_ddnatv_root_len) == 0) || is_mapped_guest_path(path); struct exec_probe probe; char resolved_target[PATH_MAX]; diff --git a/tools/nativeguest/hook/paths.c b/tools/nativeguest/hook/paths.c index cb8c66f2e..cefabd51d 100644 --- a/tools/nativeguest/hook/paths.c +++ b/tools/nativeguest/hook/paths.c @@ -100,6 +100,18 @@ static inline const char *get_rootfs_subpath(const char *target) { return NULL; } +// A guest path that a session mount puts outside the rootfs (/run/droiddeck, a game library): a +// program or script there is the guest's, and a script's "#!/bin/sh" is the rootfs shell. The +// kernel ran them with Android's /system/bin/sh, which found no /usr/bin/kwin_wayland. +static int is_mapped_guest_path(const char *path) { + if (!path || path[0] != '/') return 0; + for (int i = 0; i < g_nbinds; i++) { + const struct ddnatv_bind *b = &g_binds[i]; + if (!b->identity && is_path_prefix(path, b->dst, b->dst_len)) return 1; + } + return 0; +} + // Android's own mounts and files, which must never be redirected into the rootfs. // `path` starts with '/'; a prefix can only match when its second character does. static int is_android_host_path(const char *path) {