Skip to content

Commit

Permalink
saper!!!1111!1!!!11
Browse files Browse the repository at this point in the history
  • Loading branch information
Marcin Kościelnicki committed Jun 12, 2018
1 parent 41b4dc3 commit 7596688
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 7 deletions.
17 changes: 17 additions & 0 deletions io.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
static inline void outb(uint16_t port, uint8_t val) {
__asm__ volatile(
"outb %0, %1\n"
:
: "a"(val), "d"(port)
);
}

static inline uint8_t inb(uint16_t port) {
uint8_t res;
__asm__ volatile(
"inb %1, %0\n"
: "=a"(res)
: "d"(port)
);
return res;
}
203 changes: 199 additions & 4 deletions main.c
Original file line number Diff line number Diff line change
@@ -1,29 +1,224 @@
#include <stdint.h>
#include <stddef.h>
#include <elf.h>
#include "gdt.h"
#include "msr.h"
#include "page.h"
#include "io.h"
char hello[] = "Hello, C world!";

void *memset(void *s, int c, size_t n) {
unsigned char *p = s;
while (n--)
*p++ = c;
return s;
}

void *memcpy(void *s, void *ss, size_t n) {
unsigned char *p = s;
unsigned char *pp = ss;
while (n--)
*p++ = *pp++;
return s;
}

__asm__(
".text\n"
"go_user:\n"
"pushq $0x1b\n"
"pushq $0\n"
"pushq %rsi\n"
"pushq $0x2\n"
"pushq $0x23\n"
"pushq %rdi\n"
"iretq\n"
);

_Noreturn void go_user(void *);
__asm__(
"lstar:\n"
"pushq %rcx\n"
"pushq %r8\n"
"pushq %r9\n"
"pushq %r11\n"
"pushq %r10\n"
"pushq %rdx\n"
"pushq %rsi\n"
"pushq %rdi\n"
"movq %rax, %rdi\n"
"movq %rsp, %rsi\n"
"call csyscall\n"
"popq %rdi\n"
"popq %rsi\n"
"popq %rdx\n"
"popq %r10\n"
"popq %r11\n"
"popq %r9\n"
"popq %r8\n"
"popq %rcx\n"
"sysretq\n"
);

__asm__(
"cstar:\n"
"cli\n"
"hlt\n"
);

extern void lstar;
extern void cstar;

_Noreturn void go_user(void *, uint64_t);

void sys_print(unsigned x, unsigned y, uint16_t *chars, unsigned n) {
unsigned i;
for (i = 0; i < n; i++) {
int c = chars[i];
if (x < 80 && y < 25) {
volatile uint16_t *screen = (void *)0xffff8000000b8000ull;
screen[y * 80 + x] = c;
}
x++;
}
}

void sys_setcursor(unsigned x, unsigned y) {
if (x >= 80)
return;
if (y >= 25)
return;
unsigned addr = x + y * 80;
outb(0x3d4, 0xe);
outb(0x3d5, addr >> 8);
outb(0x3d4, 0xf);
outb(0x3d5, addr);
}

int kbd_getbyte(void) {
while (!(inb(0x64) & 1));
return inb(0x60);
}

int kbd_getcode(void) {
int k = kbd_getbyte();
if (k != 0xe0)
return k;
return kbd_getbyte() | 0x100;
}

__asm__(
".text\n"
"sys_getrand:\n"
"rdrand %eax\n"
"jnc sys_getrand\n"
"retq\n"
);
int sys_getrand(void);

int sys_getkey(void) {
int k;
while (1) {
k = kbd_getcode();
switch (k) {
case 0x1c:
return '\n';
case 0x1f:
return 's';
case 0x39:
return ' ';
case 0x14b:
return 0x81;
case 0x14d:
return 0x83;
case 0x148:
return 0x80;
case 0x150:
return 0x82;
}
}
}

uint64_t csyscall(uint64_t func, uint64_t *regs) {
switch (func) {
case 0:
outb(0x64, 0xfe);
while (1);
return 0;
case 1:
return sys_getrand();
case 2:
return sys_getkey();
case 3:
sys_print(regs[0], regs[1], (void *)regs[2], regs[3]);
return 0;
case 4:
sys_setcursor(regs[0], regs[1]);
return 0;
default:
return -1;
}
}

__asm__(
".section .rodata\n"
"user_prog:\n"
".incbin \"prog\"\n"
".text\n"
);

extern void user_prog;

void main() {
init_gdt();
init_pg();
map_page(0x31337000, phys_alloc(), 7);
// ELF loader start
Elf64_Ehdr *ehdr = &user_prog;
int i;
for (i = 0; i < ehdr->e_phnum; i++) {
Elf64_Phdr *phdr = &user_prog + ehdr->e_phoff + ehdr->e_phentsize * i;
if (phdr->p_type == PT_LOAD) {
uint64_t va = phdr->p_vaddr & ~0xfffull;
uint64_t end = phdr->p_vaddr + phdr->p_memsz;
for (uint64_t p = va; p < end; p += 0x1000) {
map_page(p, phys_alloc(), 7);
}
memset((void*)phdr->p_vaddr, 0, phdr->p_memsz);
memcpy((void*)phdr->p_vaddr, &user_prog + phdr->p_offset, phdr->p_filesz);
}
}
for (i = 0; i < ehdr->e_phnum; i++) {
Elf64_Phdr *phdr = &user_prog + ehdr->e_phoff + ehdr->e_phentsize * i;
if (phdr->p_type == 0x60031337) {
*(uint32_t *)phdr->p_vaddr = 200;
}
}
#if 0
uint8_t *upage = (void *)0x31337000ull;
upage[0] = 0xeb;
upage[1] = 0xfe;
go_user(upage);
#endif
wrmsr(0xC0000081, 0x0013000800000000ull);
wrmsr(0xC0000082, (uint64_t)&lstar);
wrmsr(0xC0000083, (uint64_t)&cstar);
wrmsr(0xC0000084, 0xffffffff);

#if 0
int x = 0;
while (1) {
int k = sys_getkey();
k = sys_getrand();
uint16_t c[2] = {
0x0f00 | (k >> 4 & 0xf)["0123456789abcdef"],
0x0f00 | (k & 0xf)["0123456789abcdef"],
};
sys_print(x, 0, c, 2);
x += 2;
x %= 80;
sys_setcursor(x, 0);
}
#endif
sys_getkey();
for (int i = 0x1000; i < 0x100000; i += 0x1000)
map_page(i, phys_alloc(), 7);
go_user((void *)ehdr->e_entry, 0x100000);
for (int i = 0; i < sizeof hello; i++) {
*(uint16_t *)(0x31337000 + i * 2) = hello[i] | 0x0f00;
}
Expand Down
9 changes: 9 additions & 0 deletions msr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
static inline void wrmsr(uint32_t reg, uint64_t val) {
uint32_t lo = val;
uint32_t hi = val >> 32;
__asm__ volatile (
"wrmsr"
:
: "a"(lo), "d"(hi), "c"(reg)
);
}
18 changes: 15 additions & 3 deletions page.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,28 @@ void map_page(uint64_t virt, uint64_t phys, int flags) {
int idx2 = virt >> 21 & 0x1ff;
int idx3 = virt >> 30 & 0x1ff;
int idx4 = virt >> 39 & 0x1ff;
if (!v_ptl4[idx4])
if (!v_ptl4[idx4]) {
v_ptl4[idx4] = phys_alloc() | 7;
uint64_t p_ptl3 = v_ptl4[idx4] & ~0xfffull;
uint64_t *v_ptl3 = P2V(p_ptl3);
memset(v_ptl3, 0, 0x1000);
}
uint64_t p_ptl3 = v_ptl4[idx4] & ~0xfffull;
uint64_t *v_ptl3 = P2V(p_ptl3);
if (!v_ptl3[idx3])
if (!v_ptl3[idx3]) {
v_ptl3[idx3] = phys_alloc() | 7;
uint64_t p_ptl2 = v_ptl3[idx3] & ~0xfffull;
uint64_t *v_ptl2 = P2V(p_ptl2);
memset(v_ptl2, 0, 0x1000);
}
uint64_t p_ptl2 = v_ptl3[idx3] & ~0xfffull;
uint64_t *v_ptl2 = P2V(p_ptl2);
if (!v_ptl2[idx2])
if (!v_ptl2[idx2]) {
v_ptl2[idx2] = phys_alloc() | 7;
uint64_t p_ptl1 = v_ptl2[idx2] & ~0xfffull;
uint64_t *v_ptl1 = P2V(p_ptl1);
memset(v_ptl1, 0, 0x1000);
}
uint64_t p_ptl1 = v_ptl2[idx2] & ~0xfffull;
uint64_t *v_ptl1 = P2V(p_ptl1);
v_ptl1[idx1] = phys | flags;
Expand Down
1 change: 1 addition & 0 deletions prog

0 comments on commit 7596688

Please sign in to comment.