implement more syscalls
This commit is contained in:
parent
93d66e8a25
commit
0f7d978071
8 changed files with 175 additions and 65 deletions
BIN
a.out
BIN
a.out
Binary file not shown.
BIN
grep
Executable file
BIN
grep
Executable file
Binary file not shown.
6
myfile
6
myfile
|
@ -1 +1,5 @@
|
|||
hello
|
||||
stuff
|
||||
stuff
|
||||
stuff
|
||||
something
|
||||
stuff
|
BIN
sam
Executable file
BIN
sam
Executable file
Binary file not shown.
49
src/main.c
49
src/main.c
|
@ -1,4 +1,3 @@
|
|||
#include "syscall.h"
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
@ -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);
|
||||
|
|
|
@ -2,10 +2,30 @@
|
|||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#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;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue