diff --git a/a.out b/a.out index 30df6b5..8e995ce 100644 Binary files a/a.out and b/a.out differ diff --git a/grep b/grep new file mode 100755 index 0000000..8786dae Binary files /dev/null and b/grep differ diff --git a/myfile b/myfile index ce01362..c15ddd1 100644 --- a/myfile +++ b/myfile @@ -1 +1,5 @@ -hello +stuff +stuff +stuff +something +stuff \ No newline at end of file diff --git a/sam b/sam new file mode 100755 index 0000000..ab8e0b3 Binary files /dev/null and b/sam differ diff --git a/src/main.c b/src/main.c index d5372c4..1e8e523 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,3 @@ -#include "syscall.h" #define _GNU_SOURCE #include #include @@ -18,12 +17,14 @@ #include "mach.h" #include "tos.h" #include "sys.h" +#include "syscall.h" #define ALIGN(v, a) (((v) + (a) - 1) & ~((a) - 1)) #define DONE_ERR(M_err, M_ret) do { fprintf(stderr, (M_err)); defer_status = (M_ret); goto done; } while(0) static char sud_intercept = SYSCALL_DISPATCH_FILTER_ALLOW; - +void *data_segment = NULL; +size_t data_segment_size = 0; extern void start(uintptr_t entry, Tos* tos, int argc, char **argv); void enter(uintptr_t entry, int argc, char **argv) @@ -45,14 +46,41 @@ void handle_sigsys(int sig, siginfo_t *info, void *ptr) int64_t *sp = (int64_t *)gregs[REG_RSP]; int64_t syscall = gregs[REG_RBP]; - printf("syscall %ld\n", syscall); + /* + printf("0x%"PRIxPTR"\n", (uintptr_t)info->si_call_addr); + + for (int i = -4; i < 3; i++) + printf("%d: 0x%"PRIxPTR"\n", i, sp[i]); + printf("donezo\n"); + */ switch (syscall) { case OPEN: ret = sys$open((char *)sp[1], (int)sp[2]); break; + case EXITS: + sys$exits((char *)sp[1]); + ret = -1; + break; + case PREAD: + ret = sys$pread((int)sp[1], (void*)sp[2], (int64_t)sp[3], (int64_t)sp[4]); + break; + case PWRITE: + ret = sys$pwrite((int)sp[1], (void*)sp[2], (int64_t)sp[3], (int64_t)sp[4]); + break; + case CLOSE: + ret = sys$close((int)sp[1]); + break; + case BRK_: + ret = sys$brk((void*)sp[1], data_segment, &data_segment_size); + break; + default: + printf("unimplemented syscall %ld\n", syscall); + break; } + //printf("ret = %ld\n", ret); + gregs[REG_RAX] = ret; } @@ -79,7 +107,7 @@ int findlibc(struct dl_phdr_info *info, size_t size, void *ptr) } static char *program_argv[] = { - "out", + "sam", "../myfile", NULL }; @@ -93,7 +121,7 @@ int main() size_t text_addr = 0x200000; size_t data_addr; - f = fopen("../a.out", "rb"); + f = fopen("../sam", "rb"); if (fread(&header, 1, sizeof(header), f) != sizeof(header)) { DONE_ERR("failed to read file header\n", 1); @@ -109,6 +137,8 @@ int main() data_addr = ALIGN(text_addr + header.text, 0x200000); + fseek(f, 0, SEEK_SET); + size_t segments_size = sizeof(Exec) + header.text + header.data; file_segments = malloc(segments_size); if (!file_segments) { @@ -125,14 +155,15 @@ int main() } printf("mapped text segment at 0x%"PRIxPTR"\n", (uintptr_t)text_segment); - void *data_segment = mmap((void*)data_addr, header.data + header.bss, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + data_segment_size = header.data + header.bss; + data_segment = mmap((void*)data_addr, data_segment_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (!text_segment) { DONE_ERR("failed to map data segment into memory\n", 1); } printf("mapped data segment at 0x%"PRIxPTR"\n", (uintptr_t)data_segment); - memcpy(text_segment, file_segments, header.text); - memcpy(data_segment, file_segments + sizeof(Exec) + header.text, header.data); + memcpy(text_segment, file_segments, header.text + sizeof(Exec)); + memcpy(data_segment, file_segments + header.text + sizeof(Exec), header.data); if (dl_iterate_phdr(findlibc, NULL) != 1) { DONE_ERR("failed to find libc and enable SUD\n", 1); @@ -144,7 +175,7 @@ int main() }; sigaction(SIGSYS, &sa, NULL); - enter(header.entry32, 2, program_argv); + enter(header.entry32, 3, program_argv); done: free(file_segments); fclose(f); diff --git a/src/sys.h b/src/sys.h index 8b7f97d..54b07fd 100644 --- a/src/sys.h +++ b/src/sys.h @@ -1,52 +1,52 @@ -#define SYSR1 0 -#define _ERRSTR 1 -#define BIND 2 -#define CHDIR 3 -#define CLOSE 4 -#define DUP 5 -#define ALARM 6 -#define EXEC 7 -#define EXITS 8 -#define _FSESSION 9 -#define FAUTH 10 -#define _FSTAT 11 -#define SEGBRK 12 -#define _MOUNT 13 -#define OPEN 14 -#define _READ 15 -#define OSEEK 16 -#define SLEEP 17 -#define _STAT 18 -#define RFORK 19 -#define _WRITE 20 -#define PIPE 21 -#define CREATE 22 -#define FD2PATH 23 -#define BRK_ 24 -#define REMOVE 25 -#define _WSTAT 26 -#define _FWSTAT 27 -#define NOTIFY 28 -#define NOTED 29 -#define SEGATTACH 30 -#define SEGDETACH 31 -#define SEGFREE 32 -#define SEGFLUSH 33 -#define RENDEZVOUS 34 -#define UNMOUNT 35 -#define _WAIT 36 -#define SEMACQUIRE 37 -#define SEMRELEASE 38 -#define SEEK 39 -#define FVERSION 40 -#define ERRSTR 41 -#define STAT 42 -#define FSTAT 43 -#define WSTAT 44 -#define FWSTAT 45 -#define MOUNT 46 -#define AWAIT 47 -#define PREAD 50 -#define PWRITE 51 -#define TSEMACQUIRE 52 -#define _NSEC 53 +#define SYSR1 0 +#define _ERRSTR 1 +#define BIND 2 +#define CHDIR 3 +#define CLOSE 4 +#define DUP 5 +#define ALARM 6 +#define EXEC 7 +#define EXITS 8 +#define _FSESSION 9 +#define FAUTH 10 +#define _FSTAT 11 +#define SEGBRK 12 +#define _MOUNT 13 +#define OPEN 14 +#define _READ 15 +#define OSEEK 16 +#define SLEEP 17 +#define _STAT 18 +#define RFORK 19 +#define _WRITE 20 +#define PIPE 21 +#define CREATE 22 +#define FD2PATH 23 +#define BRK_ 24 +#define REMOVE 25 +#define _WSTAT 26 +#define _FWSTAT 27 +#define NOTIFY 28 +#define NOTED 29 +#define SEGATTACH 30 +#define SEGDETACH 31 +#define SEGFREE 32 +#define SEGFLUSH 33 +#define RENDEZVOUS 34 +#define UNMOUNT 35 +#define _WAIT 36 +#define SEMACQUIRE 37 +#define SEMRELEASE 38 +#define SEEK 39 +#define FVERSION 40 +#define ERRSTR 41 +#define STAT 42 +#define FSTAT 43 +#define WSTAT 44 +#define FWSTAT 45 +#define MOUNT 46 +#define AWAIT 47 +#define PREAD 50 +#define PWRITE 51 +#define TSEMACQUIRE 52 +#define _NSEC 53 diff --git a/src/syscall.c b/src/syscall.c index 1809b22..75e4e23 100644 --- a/src/syscall.c +++ b/src/syscall.c @@ -2,10 +2,30 @@ #include #include #include +#include +#include +#include +#include +#include #include "syscall.h" +char *errstr = NULL; + +static int check_error(int ret) +{ + if (ret < 0) { + errstr = strerror(errno); + fprintf(stderr, "errstr says: %s\n", errstr); + return -1; + } + + return ret; +} + static int mode_open(char *name, int mode, int perm, int flag) { + printf("open %s\n", name); + switch (mode & 3) { case 0: flag |= O_RDONLY; break; case 1: flag |= O_WRONLY; break; @@ -22,7 +42,54 @@ static int mode_open(char *name, int mode, int perm, int flag) int sys$open(char *path, int mode) { - printf("sys$open(0x%"PRIxPTR", %d)\n", (uintptr_t)path, mode); - - return mode_open(path, mode, 0, 0); + return check_error(mode_open(path, mode, 0, 0)); +} + +int sys$exits(char *msg) +{ + if (!msg) { + printf("program exited successfully\n"); + exit(0); + } + + printf("program exited with error message: %s\n", msg); + exit(1); +} + +int sys$pread(int fd, void *buf, int64_t nbytes, int64_t offset) +{ + if (offset < 0) { + return check_error(read(fd, buf, nbytes)); + } + + return check_error(pread(fd, buf, nbytes, offset)); +} + +int sys$pwrite(int fd, void *buf, int64_t nbytes, int64_t offset) +{ + if (fd != 1 && fd != 2) { + fprintf(stderr, "Oh no.\n"); + exit(1); + } + + if (offset < 0) { + return check_error(write(fd, buf, nbytes)); + } + + return check_error(pwrite(fd, buf, nbytes, offset)); +} + +int sys$close(int fd) +{ + return check_error(close(fd)); +} + +int sys$brk(void *addr, void *_data_segment, size_t *_data_segment_size) +{ + size_t new_size = addr - _data_segment; + if (mremap(_data_segment, *_data_segment_size, new_size, 0) == MAP_FAILED) { + return -1; + } + *_data_segment_size = new_size; + return 0; } diff --git a/src/syscall.h b/src/syscall.h index 188cc81..dada2e0 100644 --- a/src/syscall.h +++ b/src/syscall.h @@ -1,3 +1,11 @@ #pragma once +#include +#include + int sys$open(char *path, int mode); +int sys$exits(char *msg); +int sys$pread(int fd, void *buf, int64_t nbytes, int64_t offset); +int sys$pwrite(int fd, void *buf, int64_t nbytes, int64_t offset); +int sys$close(int fd); +int sys$brk(void *addr, void *_data_segment, size_t *_data_segment_size);