/* * Shebang trampoline: run a script with persist bash + persist glibc. * vdb /usr/bin/bash needs libreadline, and virtio often returns a bad * ext4 inode checksum for that file. persist userland is on vdc. * * Built like utsm_exec_daemon: -static -fcf-protection=none. */ #define _GNU_SOURCE #include #include #include #include #include extern char **environ; static void kmsg(const char *s) { int fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); if (fd < 0) return; (void)write(fd, s, strlen(s)); close(fd); } static int exists(const char *p) { return p && access(p, X_OK) == 0; } int main(int argc, char **argv) { static const char *ld_cands[] = { "/mnt/persist/usr/lib/ld-linux-x86-64.so.2", "/mnt/persist/lib64/ld-linux-x86-64.so.2", "/mnt/persist/lib/ld-linux-x86-64.so.2", 0 }; static const char *bash_cands[] = { "/mnt/persist/usr/bin/bash", "/mnt/persist/bin/bash", 0 }; const char *libpath = "/mnt/persist/usr/lib:/mnt/persist/lib64:/mnt/persist/lib"; const char *path = "/mnt/persist/usr/bin:/mnt/persist/bin:/usr/local/bin:/usr/bin:/bin"; const char *ld = 0; const char *bash = 0; char *nargv[64]; int n = 0; int i; char line[192]; kmsg("[utsm_run] start\n"); if (argc < 2) { kmsg("[utsm_run] usage: utsm_run script [args]\n"); return 2; } /* Already inside persist chroot: /mnt/persist is gone, bash is local. */ if (access("/etc/deshab-kde-root", F_OK) == 0 || access("/mnt/persist/usr/bin/bash", X_OK) != 0) { kmsg("[utsm_run] inside persist, exec /usr/bin/bash\n"); nargv[n++] = "/usr/bin/bash"; for (i = 1; i < argc && n < 62; i++) nargv[n++] = argv[i]; nargv[n] = 0; execv("/usr/bin/bash", nargv); kmsg("[utsm_run] inside bash execv failed\n"); return 127; } setenv("PATH", path, 1); setenv("LD_LIBRARY_PATH", libpath, 1); setenv("GLIBC_TUNABLES", "glibc.cpu.hwcaps=-IBT,-SHSTK", 1); for (i = 0; ld_cands[i]; i++) { if (exists(ld_cands[i])) { ld = ld_cands[i]; break; } } for (i = 0; bash_cands[i]; i++) { if (exists(bash_cands[i])) { bash = bash_cands[i]; break; } } /* persist ld.so (as program or as PT_INTERP) SIGSEGVs at -40 in * _dl_find_dso_for_object. Use vdb's RAM-backed interpreter with * persist libraries via LD_LIBRARY_PATH. */ (void)ld; if (bash) { snprintf(line, sizeof(line), "[utsm_run] persist bash %s\n", bash); kmsg(line); nargv[n++] = (char *)bash; for (i = 1; i < argc && n < 62; i++) nargv[n++] = argv[i]; nargv[n] = 0; execve(bash, nargv, environ); kmsg("[utsm_run] persist bash execve failed\n"); } kmsg("[utsm_run] fallback /usr/bin/bash\n"); n = 0; nargv[n++] = "/usr/bin/bash"; for (i = 1; i < argc && n < 62; i++) nargv[n++] = argv[i]; nargv[n] = 0; execv("/usr/bin/bash", nargv); kmsg("[utsm_run] fallback execv failed\n"); return 127; }