racket-static/startup.c

101 lines
2.9 KiB
C

#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdbool.h>
void crimes_startup_run(uint8_t* frame) {
// we trash argv up to hack on ld.so arguments without needing malloc
// this is pad space to catch that and not explode uwu
volatile char _pad[(sizeof(char*) * 4)];
// XXX: assumes stack goes up
// big weh
size_t argc = *((size_t*) (frame + sizeof(size_t)));
char** argv = ((char**) (frame + sizeof(size_t) + sizeof(char*)));
char** envp = argv + argc + 1;
// fake usage of _pad
// also a barrier to ensure argc gets read
asm volatile("" :: "rm"(_pad) : "memory");
syscall(SYS_write, STDOUT_FILENO, "[crimes] detect maps\n", 21);
int fd = syscall(SYS_open, "/proc/self/maps", O_RDONLY);
if (fd < 0) {
syscall(SYS_write, STDOUT_FILENO, "[crimes] open failed\n", 21);
syscall(SYS_exit, -1);
}
char buf[32];
int state = 0;
while (true) {
ssize_t res = syscall(SYS_read, fd, buf, sizeof(buf));
if (res == 0) {
break;
} else if (res < 0) {
syscall(SYS_write, STDOUT_FILENO, "[crimes] read error\n", 20);
syscall(SYS_exit, -1);
}
for (ssize_t i = 0; i < res; i++) {
switch (state) {
case 0:
if (buf[i] == '/') { state++; }
else { state = 0; }
break;
case 1:
if (buf[i] == 'l') { state++; }
else { state = 0; }
break;
case 2:
if (buf[i] == 'd') { state++; }
else { state = 0; }
break;
case 3:
if (buf[i] == '-') { state++; }
else { state = 0; }
break;
default:
break;
}
if (state > 3) {
break;
}
}
if (state > 3) {
break;
}
}
if (state > 3) {
syscall(SYS_write, STDOUT_FILENO, "[crimes] detected libc. going back to startup\n", 46);
return;
}
syscall(SYS_write, STDOUT_FILENO, "[crimes] running ld.so\n", 23);
// XXX: currently we hardcode the glibc parameters
// detect glibc or musl at runtime and load the appropriate params
char* ld = "/usr/lib/ld-2.32.so";
char* pl = "--preload";
char* ldlp =
"/usr/lib/libm.so.6:/usr/lib/libpthread.so.0:/usr/lib/libdl.so.2:/usr/lib/libc.so.6";
uintptr_t args[4 + argc];
args[0] = (uintptr_t)ld;
args[1] = (uintptr_t)pl;
args[2] = (uintptr_t)ldlp;
for (size_t i = 0; i < argc; i++) {
args[3 + i] = (uintptr_t) argv[i];
}
args[3 + argc] = 0;
syscall(SYS_execve, ld, args, envp);
syscall(SYS_write, STDOUT_FILENO, "[crimes] exec failed!\n", 22);
syscall(SYS_exit, -1);
}