fl/main.c

183 lines
3.7 KiB
C
Raw Permalink Normal View History

2023-11-22 11:22:58 -08:00
#include <stdint.h>
#include <sys/syscall.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
2023-12-13 21:05:35 -08:00
extern void cat(int fd, long sz);
#ifndef __FreeBSD__
#include <sys/prctl.h>
2023-11-22 11:22:58 -08:00
#define SYSCT_FBSD 588
2023-11-28 11:34:13 -08:00
uint8_t sel = SYSCALL_DISPATCH_FILTER_ALLOW;
2023-11-22 11:22:58 -08:00
uint16_t scmap[SYSCT_FBSD] = {
-1, // SYS_syscall needs args shifted
SYS_exit,
-1, // SYS_fork needs sud reset
SYS_read,
SYS_write,
SYS_open,
SYS_close,
-1, // wait4
-1, // [old] creat
SYS_link,
SYS_unlink,
-1, // [obsolete] execv
SYS_chdir,
2023-11-28 11:34:13 -08:00
SYS_fchdir,
-1, // [freebsd11] mknod
SYS_chmod,
SYS_chown,
-1, // break (no manual)
-1, // [freebsd4] getfsstat
-1, // [old] lseek
SYS_getpid,
2023-11-22 11:22:58 -08:00
};
2023-11-28 11:34:13 -08:00
// TODO also create trampoline for freebsd native signals
void systrap(int n, siginfo_t* s, ucontext_t* c) {
2023-11-22 11:22:58 -08:00
sel = SYSCALL_DISPATCH_FILTER_ALLOW;
2023-11-28 11:34:13 -08:00
if(s->si_code != /* SYS_USER_DISPATCH - value from <asm-generic/siginfo.h> */ 2) {
// TODO chain old syscall handler
} else if(s->si_syscall > SYSCT_FBSD-1) {
// TODO fail - check how freebsd does this, esp. with nosys entries
} else if(scmap[s->si_syscall] == -1) {
switch(s->si_syscall) {
default:
abort();
break;
}
}
// TODO find max arg ct. and check stack if needed
2023-11-22 11:22:58 -08:00
c->uc_mcontext.gregs[13] = syscall(
scmap[s->si_syscall],
c->uc_mcontext.gregs[8],
c->uc_mcontext.gregs[9],
c->uc_mcontext.gregs[12]
);
//for(int i = 0; i < 23; i++) printf("%i: %lX\n", i, c->uc_mcontext.gregs[i]);
sel = SYSCALL_DISPATCH_FILTER_BLOCK;
}
2023-12-13 21:05:35 -08:00
#endif
2023-11-22 11:22:58 -08:00
typedef struct {
uint8_t magic[4];
uint8_t bits;
uint8_t endian;
uint8_t hdrver;
uint8_t abi;
uint8_t pad[8];
uint16_t type;
uint16_t isa;
uint32_t ver;
uint64_t ep;
uint64_t phtable;
uint64_t shtable;
uint32_t flags;
uint16_t hsz;
uint16_t phtesz;
uint16_t phtct;
uint16_t shtesz;
uint16_t shtct;
uint16_t nameind;
} __attribute__((packed)) elf;
2023-12-13 21:05:35 -08:00
#ifndef __FreeBSD__
2023-11-22 11:22:58 -08:00
char** getmaps(int* tsz) {
int fd = open("/proc/self/maps", O_RDONLY);
char c;
*tsz = 0;
int p = 0, s = 128;
char** t = malloc(sizeof(char*));
t[0] = malloc(s);
while(read(fd, &c, 1)) {
if(c == '\n') c = 0;
t[*tsz][p++] = c;
if(p >= s) t[*tsz] = realloc(t[*tsz], s += 8);
if(!c) {
t = realloc(t, ((++(*tsz)) + 1) * sizeof(char*));
t[*tsz] = malloc(s = 128);
p = 0;
}
}
(*tsz)++;
close(fd);
return t;
}
typedef struct {
uint64_t start;
uint64_t len;
uint8_t rwx;
char* name;
} map;
void stomap(char* s, map* m) {
m->start = 0;
m->len = 0;
m->rwx = 0;
while(*s != '-') {
m->start <<= 4;
if(*s >= '0' && *s <= '9') m->start |= *s - '0';
else m->start |= *s - 'a' + 10;
s++;
}
s++;
while(*s != ' ') {
m->len <<= 4;
if(*s >= '0' && *s <= '9') m->len |= *s - '0';
else m->len |= *s - 'a' + 10;
s++;
}
s++;
for(int i = 0; i < 3; i++) {
m->rwx <<= 1;
m->rwx |= (*(s++) != '-');
}
s += 2;
while(*(s++) != ':');
while(*(s++) != ' ');
while(*s >= '0' && *s <= '9') s++;
while(*(++s) == ' ');
int d = strlen(s) + 1;
m->name = memcpy(malloc(d), s, d);
m->len -= m->start;
}
2023-12-13 21:05:35 -08:00
#endif
2023-11-22 11:22:58 -08:00
int main(int argc, char** argv) {
2023-12-13 21:05:35 -08:00
#ifndef __FreeBSD__
2023-11-22 11:22:58 -08:00
struct sigaction a, oa;
sigemptyset(&a.sa_mask);
a.sa_flags = SA_SIGINFO;
2023-11-28 11:34:13 -08:00
a.sa_sigaction = (void(*)(int, siginfo_t*, void*))systrap;
2023-11-22 11:22:58 -08:00
int nm;
char** smaps = getmaps(&nm);
2023-11-28 11:34:13 -08:00
2023-12-13 21:05:35 -08:00
for(int i = 0; i < nm-1; i++) if(strstr(smaps[i], "libc")) {
map rmap;
stomap(smaps[i], &rmap);
if(rmap.rwx & 1) prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, rmap.start, rmap.len, &sel);
2023-11-22 11:22:58 -08:00
}
for(int i = 0; i < nm; i++) free(smaps[i]);
free(smaps);
2023-12-13 21:05:35 -08:00
#endif
2023-11-22 11:22:58 -08:00
if(argc < 2) return printf("no file provided\n");
int fd = open(argv[1], O_RDONLY);
struct stat s;
fstat(fd, &s);
2023-12-13 21:05:35 -08:00
#ifndef __FreeBSD__
2023-11-28 11:34:13 -08:00
sigaction(SIGSYS, &a, &oa);
2023-11-22 11:22:58 -08:00
sel = SYSCALL_DISPATCH_FILTER_BLOCK;
2023-12-13 21:05:35 -08:00
#endif
2023-11-22 11:22:58 -08:00
cat(fd, s.st_size);
}