implement more syscalls

This commit is contained in:
hippoz 2023-07-25 11:52:47 +03:00
parent 93d66e8a25
commit 0f7d978071
Signed by: hippoz
GPG key ID: 56C4E02A85F2FBED
8 changed files with 175 additions and 65 deletions

BIN
a.out

Binary file not shown.

BIN
grep Executable file

Binary file not shown.

6
myfile
View file

@ -1 +1,5 @@
hello
stuff
stuff
stuff
something
stuff

BIN
sam Executable file

Binary file not shown.

View file

@ -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);

View file

@ -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;
}

View file

@ -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);