Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ endif

# If the makefile can't find QEMU, specify its path here
# QEMU = qemu-system-i386

QEMU = /usr/libexec/qemu-kvm
# Try to infer the correct QEMU
ifndef QEMU
QEMU = $(shell if which qemu > /dev/null; \
Expand Down Expand Up @@ -146,14 +146,14 @@ vectors.S: vectors.pl
ULIB = ulib.o usys.o printf.o umalloc.o

_%: %.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $@ $^
$(LD) $(LDFLAGS) -N -e main -Ttext 0x1000 -o $@ $^
$(OBJDUMP) -S $@ > $*.asm
$(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym

_forktest: forktest.o $(ULIB)
# forktest has less library code linked in - needs to be small
# in order to be able to max out the proc table.
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o _forktest forktest.o ulib.o usys.o
$(LD) $(LDFLAGS) -N -e main -Ttext 0x1000 -o _forktest forktest.o ulib.o usys.o
$(OBJDUMP) -S _forktest > forktest.asm

mkfs: mkfs.c fs.h
Expand Down Expand Up @@ -181,6 +181,8 @@ UPROGS=\
_usertests\
_wc\
_zombie\
_testkaccess\
_testnull\

fs.img: mkfs README $(UPROGS)
./mkfs fs.img README $(UPROGS)
Expand Down Expand Up @@ -283,4 +285,4 @@ tar:
cp dist/* dist/.gdbinit.tmpl /tmp/xv6
(cd /tmp; tar cf - xv6) | gzip >xv6-rev10.tar.gz # the next one will be 10 (9/17)

.PHONY: dist-test dist
.PHONY: dist-test dist
7 changes: 7 additions & 0 deletions defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ int fetchint(uint, int*);
int fetchstr(uint, char**);
void syscall(void);

// sysproc.c
int sys_mprotect(void);
int sys_munprotect(void);

// timer.c
void timerinit(void);

Expand All @@ -181,10 +185,13 @@ void freevm(pde_t*);
void inituvm(pde_t*, char*, uint);
int loaduvm(pde_t*, char*, struct inode*, uint, uint);
pde_t* copyuvm(pde_t*, uint);
pde_t* walkpgdir(pde_t *pgdir, const void *va, int alloc);
void switchuvm(struct proc*);
void switchkvm(void);
int copyout(pde_t*, uint, void*, uint);
void clearpteu(pde_t *pgdir, char *uva);
int mprotectpages(void*, int);
int munprotectpages(void*, int);

// number of elements in fixed-size array
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
4 changes: 2 additions & 2 deletions exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ exec(char *path, char **argv)
goto bad;

// Load program into memory.
sz = 0;
sz = PGSIZE;
for(i=0, off=elf.phoff; i<elf.phnum; i++, off+=sizeof(ph)){
if(readi(ip, (char*)&ph, off, sizeof(ph)) != sizeof(ph))
goto bad;
Expand Down Expand Up @@ -111,4 +111,4 @@ exec(char *path, char **argv)
end_op();
}
return -1;
}
}
28 changes: 25 additions & 3 deletions syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,13 @@ fetchint(uint addr, int *ip)
{
struct proc *curproc = myproc();

if(addr >= curproc->sz || addr+4 > curproc->sz)
if(addr >= curproc->sz)
return -1;
if(addr + 4 > curproc->sz)
return -1;
if(addr + 4 < addr)
return -1;

*ip = *(int*)(addr);
return 0;
}
Expand All @@ -36,8 +41,10 @@ fetchstr(uint addr, char **pp)

if(addr >= curproc->sz)
return -1;

*pp = (char*)addr;
ep = (char*)curproc->sz;

for(s = *pp; s < ep; s++){
if(*s == 0)
return s - *pp;
Expand All @@ -63,8 +70,19 @@ argptr(int n, char **pp, int size)

if(argint(n, &i) < 0)
return -1;
if(size < 0 || (uint)i >= curproc->sz || (uint)i+size > curproc->sz)

if(size < 0)
return -1;

if((uint)i >= curproc->sz)
return -1;

if((uint)i + size > curproc->sz)
return -1;

if((uint)i + size < (uint)i)
return -1;

*pp = (char*)i;
return 0;
}
Expand Down Expand Up @@ -103,6 +121,8 @@ extern int sys_unlink(void);
extern int sys_wait(void);
extern int sys_write(void);
extern int sys_uptime(void);
extern int sys_mprotect(void);
extern int sys_munprotect(void);

static int (*syscalls[])(void) = {
[SYS_fork] sys_fork,
Expand All @@ -126,6 +146,8 @@ static int (*syscalls[])(void) = {
[SYS_link] sys_link,
[SYS_mkdir] sys_mkdir,
[SYS_close] sys_close,
[SYS_mprotect] sys_mprotect,
[SYS_munprotect] sys_munprotect,
};

void
Expand All @@ -142,4 +164,4 @@ syscall(void)
curproc->pid, curproc->name, num);
curproc->tf->eax = -1;
}
}
}
2 changes: 2 additions & 0 deletions syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@
#define SYS_link 19
#define SYS_mkdir 20
#define SYS_close 21
#define SYS_mprotect 22
#define SYS_munprotect 23
56 changes: 56 additions & 0 deletions sysproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,3 +89,59 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}

int
sys_mprotect(void)
{
char *addr;
int len;

if(argptr(0, &addr, sizeof(addr)) < 0)
return -1;
if(argint(1, &len) < 0)
return -1;

if((uint)addr % PGSIZE != 0 || len <= 0)
return -1;

struct proc *p = myproc();

for(int i = 0; i < len; i += PGSIZE) {
pte_t *pte = walkpgdir(p->pgdir, addr + i, 0);
if(!pte || !(*pte & PTE_P))
return -1;

*pte &= ~PTE_W;
}

return 0;
}

int
sys_munprotect(void)
{
char *addr;
int len;

if(argptr(0, &addr, sizeof(addr)) < 0)
return -1;
if(argint(1, &len) < 0)
return -1;

if((uint)addr % PGSIZE != 0 || len <= 0)
return -1;

struct proc *p = myproc();

for(int i = 0; i < len; i += PGSIZE) {
pte_t *pte = walkpgdir(p->pgdir, addr + i, 0);
if(!pte || !(*pte & PTE_P))
return -1;

*pte |= PTE_W;
}

lcr3(V2P(p->pgdir));

return 0;
}
11 changes: 11 additions & 0 deletions testkaccess.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "types.h"
#include "stat.h"
#include "user.h"

int main(void){
printf(1, "testkaccess: illegal read attempt\n");
volatile int *p = (int*)0xFFFF0000;
volatile int x = *p;
printf(1, "UNEXPECTED: read=%d\n", x);
exit();
}
11 changes: 11 additions & 0 deletions testnull.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "types.h"
#include "stat.h"
#include "user.h"

int main(void){
printf(1, "testnull: about to dereference NULL\n");
volatile int *p = (int*)0x0;
volatile int x = *p;
printf(1, "UNEXPECTED: read=%d\n", x);
exit();
}
27 changes: 25 additions & 2 deletions trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ trap(struct trapframe *tf)
break;

//PAGEBREAK: 13
default:
/*default:
if(myproc() == 0 || (tf->cs&3) == 0){
// In kernel, it must be our mistake.
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
Expand All @@ -92,6 +92,29 @@ trap(struct trapframe *tf)
myproc()->pid, myproc()->name, tf->trapno,
tf->err, cpuid(), tf->eip, rcr2());
myproc()->killed = 1;
}*/

default:
if(myproc() == 0 || (tf->cs&3) == 0){
// Kernel mode → panic
cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
tf->trapno, cpuid(), tf->eip, rcr2());
panic("trap");
}

// Special handling for page fault
if(tf->trapno == T_PGFLT){
cprintf("pid %d %s: page fault at addr 0x%x, eip 0x%x\n",
myproc()->pid, myproc()->name, rcr2(), tf->eip);
} else {
cprintf("pid %d %s: trap %d err %d on cpu %d "
"eip 0x%x addr 0x%x--kill proc\n",
myproc()->pid, myproc()->name, tf->trapno,
tf->err, cpuid(), tf->eip, rcr2());
}

myproc()->killed = 1;
break;
}

// Force process exit if it has been killed and is in user space.
Expand All @@ -109,4 +132,4 @@ trap(struct trapframe *tf)
// Check if the process has been killed since we yielded
if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
exit();
}
}
4 changes: 3 additions & 1 deletion user.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ int getpid(void);
char* sbrk(int);
int sleep(int);
int uptime(void);
int mprotect(void*, int);
int munprotect(void*, int);

// ulib.c
int stat(const char*, struct stat*);
Expand All @@ -36,4 +38,4 @@ uint strlen(const char*);
void* memset(void*, int, uint);
void* malloc(uint);
void free(void*);
int atoi(const char*);
int atoi(const char*);
2 changes: 2 additions & 0 deletions usys.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ SYSCALL(getpid)
SYSCALL(sbrk)
SYSCALL(sleep)
SYSCALL(uptime)
SYSCALL(mprotect)
SYSCALL(munprotect)
9 changes: 4 additions & 5 deletions vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ seginit(void)
// Return the address of the PTE in page table pgdir
// that corresponds to virtual address va. If alloc!=0,
// create any required page table pages.
static pte_t *
pte_t *
walkpgdir(pde_t *pgdir, const void *va, int alloc)
{
pde_t *pde;
Expand Down Expand Up @@ -323,10 +323,9 @@ copyuvm(pde_t *pgdir, uint sz)
if((d = setupkvm()) == 0)
return 0;
for(i = 0; i < sz; i += PGSIZE){
if((pte = walkpgdir(pgdir, (void *) i, 0)) == 0)
panic("copyuvm: pte should exist");
if(!(*pte & PTE_P))
panic("copyuvm: page not present");
pte = walkpgdir(pgdir, (void*)i, 0);
if(pte == 0 || !(*pte & PTE_P))
continue;
pa = PTE_ADDR(*pte);
flags = PTE_FLAGS(*pte);
if((mem = kalloc()) == 0)
Expand Down