summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--kernel/defs.h2
-rw-r--r--kernel/exec.c21
-rw-r--r--kernel/proc.c2
-rw-r--r--kernel/vm.c4
-rw-r--r--user/user.ld36
-rw-r--r--user/usertests.c111
7 files changed, 126 insertions, 52 deletions
diff --git a/Makefile b/Makefile
index 6f0f40e..39a99d7 100644
--- a/Makefile
+++ b/Makefile
@@ -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},
};