diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | kernel/defs.h | 2 | ||||
-rw-r--r-- | kernel/exec.c | 21 | ||||
-rw-r--r-- | kernel/proc.c | 2 | ||||
-rw-r--r-- | kernel/vm.c | 4 | ||||
-rw-r--r-- | user/user.ld | 36 | ||||
-rw-r--r-- | user/usertests.c | 111 |
7 files changed, 126 insertions, 52 deletions
@@ -90,7 +90,7 @@ tags: $(OBJS) _init ULIB = $U/ulib.o $U/usys.o $U/printf.o $U/umalloc.o _%: %.o $(ULIB) - $(LD) $(LDFLAGS) -N -e _main -Ttext 0 -o $@ $^ + $(LD) $(LDFLAGS) -T $U/user.ld -o $@ $^ $(OBJDUMP) -S $@ > $*.asm $(OBJDUMP) -t $@ | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$$/d' > $*.sym diff --git a/kernel/defs.h b/kernel/defs.h index 7457b66..95fb94b 100644 --- a/kernel/defs.h +++ b/kernel/defs.h @@ -162,7 +162,7 @@ void kvmmap(pagetable_t, uint64, uint64, uint64, int); int mappages(pagetable_t, uint64, uint64, uint64, int); pagetable_t uvmcreate(void); void uvmfirst(pagetable_t, uchar *, uint); -uint64 uvmalloc(pagetable_t, uint64, uint64); +uint64 uvmalloc(pagetable_t, uint64, uint64, int); uint64 uvmdealloc(pagetable_t, uint64, uint64); int uvmcopy(pagetable_t, pagetable_t, uint64); void uvmfree(pagetable_t, uint64); diff --git a/kernel/exec.c b/kernel/exec.c index 09b4bdc..e18bbb6 100644 --- a/kernel/exec.c +++ b/kernel/exec.c @@ -7,7 +7,17 @@ #include "defs.h" #include "elf.h" -static int loadseg(pde_t *pgdir, uint64 addr, struct inode *ip, uint offset, uint sz); +static int loadseg(pde_t *, uint64, struct inode *, uint, uint); + +int flags2perm(int flags) +{ + int perm = 0; + if(flags & 0x1) + perm = PTE_X; + if(flags & 0x2) + perm |= PTE_W; + return perm; +} int exec(char *path, char **argv) @@ -32,6 +42,7 @@ exec(char *path, char **argv) // Check ELF header if(readi(ip, 0, (uint64)&elf, 0, sizeof(elf)) != sizeof(elf)) goto bad; + if(elf.magic != ELF_MAGIC) goto bad; @@ -48,12 +59,12 @@ exec(char *path, char **argv) goto bad; if(ph.vaddr + ph.memsz < ph.vaddr) goto bad; + if(ph.vaddr % PGSIZE != 0) + goto bad; uint64 sz1; - if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz)) == 0) + if((sz1 = uvmalloc(pagetable, sz, ph.vaddr + ph.memsz, flags2perm(ph.flags))) == 0) goto bad; sz = sz1; - if((ph.vaddr % PGSIZE) != 0) - goto bad; if(loadseg(pagetable, ph.vaddr, ip, ph.off, ph.filesz) < 0) goto bad; } @@ -69,7 +80,7 @@ exec(char *path, char **argv) // Use the second as the user stack. sz = PGROUNDUP(sz); uint64 sz1; - if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE)) == 0) + if((sz1 = uvmalloc(pagetable, sz, sz + 2*PGSIZE, PTE_W)) == 0) goto bad; sz = sz1; uvmclear(pagetable, sz-2*PGSIZE); diff --git a/kernel/proc.c b/kernel/proc.c index 8d0ca8c..959b778 100644 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -264,7 +264,7 @@ growproc(int n) sz = p->sz; if(n > 0){ - if((sz = uvmalloc(p->pagetable, sz, sz + n)) == 0) { + if((sz = uvmalloc(p->pagetable, sz, sz + n, PTE_W)) == 0) { return -1; } } else if(n < 0){ diff --git a/kernel/vm.c b/kernel/vm.c index 3c6f295..284b72d 100644 --- a/kernel/vm.c +++ b/kernel/vm.c @@ -218,7 +218,7 @@ uvmfirst(pagetable_t pagetable, uchar *src, uint sz) // Allocate PTEs and physical memory to grow process from oldsz to // newsz, which need not be page aligned. Returns new size or 0 on error. uint64 -uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) +uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz, int xperm) { char *mem; uint64 a; @@ -234,7 +234,7 @@ uvmalloc(pagetable_t pagetable, uint64 oldsz, uint64 newsz) return 0; } memset(mem, 0, PGSIZE); - if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_W|PTE_X|PTE_R|PTE_U) != 0){ + if(mappages(pagetable, a, PGSIZE, (uint64)mem, PTE_R|PTE_U|xperm) != 0){ kfree(mem); uvmdealloc(pagetable, a, oldsz); return 0; diff --git a/user/user.ld b/user/user.ld new file mode 100644 index 0000000..0ca922b --- /dev/null +++ b/user/user.ld @@ -0,0 +1,36 @@ +OUTPUT_ARCH( "riscv" ) +ENTRY( _main ) + + +SECTIONS +{ + . = 0x0; + + .text : { + *(.text .text.*) + } + + .rodata : { + . = ALIGN(16); + *(.srodata .srodata.*) /* do not need to distinguish this from .rodata */ + . = ALIGN(16); + *(.rodata .rodata.*) + . = ALIGN(0x1000); + } + + .data : { + . = ALIGN(16); + *(.sdata .sdata.*) /* do not need to distinguish this from .data */ + . = ALIGN(16); + *(.data .data.*) + } + + .bss : { + . = ALIGN(16); + *(.sbss .sbss.*) /* do not need to distinguish this from .bss */ + . = ALIGN(16); + *(.bss .bss.*) + } + + PROVIDE(end = .); +} diff --git a/user/usertests.c b/user/usertests.c index 60d1762..7c31013 100644 --- a/user/usertests.c +++ b/user/usertests.c @@ -2508,17 +2508,40 @@ stacktest(char *s) exit(xstatus); } +// check that writes to text segment fault +void +texttest(char *s) +{ + int pid; + int xstatus; + + pid = fork(); + if(pid == 0) { + volatile int *addr = (int *) 0; + *addr = 10; + exit(1); + } else if(pid < 0){ + printf("%s: fork failed\n", s); + exit(1); + } + wait(&xstatus); + if(xstatus == -1) // kernel killed child? + exit(0); + else + exit(xstatus); +} + // regression test. copyin(), copyout(), and copyinstr() used to cast // the virtual page address to uint, which (with certain wild system // call arguments) resulted in a kernel page faults. +void *big = (void*) 0xeaeb0b5b00002f5e; void pgbug(char *s) { char *argv[1]; argv[0] = 0; - exec((char*)0xeaeb0b5b00002f5e, argv); - - pipe((int*)0xeaeb0b5b00002f5e); + exec(big, argv); + pipe(big); exit(0); } @@ -2607,6 +2630,7 @@ sbrklast(char *s) exit(1); } + // does sbrk handle signed int32 wrap-around with // negative arguments? void @@ -2617,6 +2641,7 @@ sbrk8000(char *s) *(top-1) = *(top-1) + 1; } + // regression test. does write() with an invalid buffer pointer cause // a block to be allocated for a file that is then not freed when the // file is deleted? if the kernel has this bug, it will panic: balloc: @@ -2896,9 +2921,6 @@ main(int argc, char *argv[]) void (*f)(char *); char *s; } tests[] = { - {diskfull, "diskfull"}, - {manywrites, "manywrites"}, - {execout, "execout"}, {copyin, "copyin"}, {copyout, "copyout"}, {copyinstr1, "copyinstr1"}, @@ -2908,58 +2930,63 @@ main(int argc, char *argv[]) {truncate1, "truncate1"}, {truncate2, "truncate2"}, {truncate3, "truncate3"}, - {reparent2, "reparent2"}, - {pgbug, "pgbug" }, - {sbrkbugs, "sbrkbugs" }, - // {badwrite, "badwrite" }, - {badarg, "badarg" }, + {openiputtest, "openiput"}, + {exitiputtest, "exitiput"}, + {iputtest, "iput"}, + {opentest, "opentest"}, + {writetest, "writetest"}, + {writebig, "writebig"}, + {createtest, "createtest"}, + {dirtest, "dirtest"}, + {exectest, "exectest"}, + {pipe1, "pipe1"}, + {killstatus, "killstatus"}, + {preempt, "preempt"}, + {exitwait, "exitwait"}, {reparent, "reparent" }, {twochildren, "twochildren"}, {forkfork, "forkfork"}, {forkforkfork, "forkforkfork"}, - {argptest, "argptest"}, + {reparent2, "reparent2"}, + {mem, "mem"}, + {sharedfd, "sharedfd"}, + {fourfiles, "fourfiles"}, {createdelete, "createdelete"}, - {linkunlink, "linkunlink"}, - {linktest, "linktest"}, {unlinkread, "unlinkread"}, + {linktest, "linktest"}, {concreate, "concreate"}, + {linkunlink, "linkunlink"}, + {bigdir, "bigdir"}, // slow {subdir, "subdir"}, - {fourfiles, "fourfiles"}, - {sharedfd, "sharedfd"}, - {dirtest, "dirtest"}, - {exectest, "exectest"}, - {bigargtest, "bigargtest"}, {bigwrite, "bigwrite"}, - {bsstest, "bsstest"}, + {manywrites, "manywrites"}, + {bigfile, "bigfile"}, + {fourteen, "fourteen"}, + {rmdot, "rmdot"}, + {dirfile, "dirfile"}, + {iref, "iref"}, + {forktest, "forktest"}, {sbrkbasic, "sbrkbasic"}, {sbrkmuch, "sbrkmuch"}, {kernmem, "kernmem"}, + {MAXVAplus, "MAXVAplus"}, {sbrkfail, "sbrkfail"}, {sbrkarg, "sbrkarg"}, - {sbrklast, "sbrklast"}, - {sbrk8000, "sbrk8000"}, {validatetest, "validatetest"}, + {bsstest, "bsstest"}, + {bigargtest, "bigargtest"}, + {argptest, "argptest"}, {stacktest, "stacktest"}, - {opentest, "opentest"}, - {writetest, "writetest"}, - {writebig, "writebig"}, - {createtest, "createtest"}, - {openiputtest, "openiput"}, - {exitiputtest, "exitiput"}, - {iputtest, "iput"}, - {mem, "mem"}, - {pipe1, "pipe1"}, - {killstatus, "killstatus"}, - {preempt, "preempt"}, - {exitwait, "exitwait"}, - {rmdot, "rmdot"}, - {fourteen, "fourteen"}, - {bigfile, "bigfile"}, - {dirfile, "dirfile"}, - {iref, "iref"}, - {forktest, "forktest"}, - {MAXVAplus, "MAXVAplus"}, - {bigdir, "bigdir"}, // slow + {pgbug, "pgbug" }, + {sbrkbugs, "sbrkbugs" }, + {sbrklast, "sbrklast"}, + {sbrk8000, "sbrk8000"}, + {badwrite, "badwrite" }, + {badarg, "badarg" }, + {execout, "execout"}, + {diskfull, "diskfull"}, + {texttest, "texttest"}, + { 0, 0}, }; |