117 lines
3.2 KiB
C
117 lines
3.2 KiB
C
/*
|
|
* 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 <fcntl.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
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;
|
|
}
|