diff --git a/kern/pmap.c b/kern/pmap.c index 2c590f2..9bd5767 100644 --- a/kern/pmap.c +++ b/kern/pmap.c @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -562,6 +563,21 @@ int user_mem_check(struct Env *env, const void *va, size_t len, int perm) { // LAB 3: Your code here. + const char* bottom = ROUNDDOWN(va, PGSIZE); + size_t aligned_count = ROUNDUP(len, PGSIZE) / PGSIZE; + pde_t mask = PTE_P | PTE_U | PTE_W; + pde_t perms = mask; + +#define VALID ((perms & (perm | PTE_P)) == (perm | PTE_P)) +#define DO_CHECK if(!VALID) { user_mem_check_addr = (uintptr_t) bottom; return -E_FAULT; } + + while(aligned_count--) { + perms &= env->env_pgdir[PDX(bottom)] & mask; + DO_CHECK; + perms &= (*pgdir_walk(env->env_pgdir, bottom, 0)) & mask; + DO_CHECK; + bottom += PGSIZE; + } return 0; } diff --git a/kern/syscall.c b/kern/syscall.c index 59adfa7..d332f11 100644 --- a/kern/syscall.c +++ b/kern/syscall.c @@ -19,26 +19,7 @@ sys_cputs(const char *s, size_t len) { // Check that the user has permission to read memory [s, s+len). // Destroy the environment if not. - const char* bottom = ROUNDDOWN(s, PGSIZE); - size_t aligned_count = ROUNDUP(len, PGSIZE) / PGSIZE; - while(aligned_count--) { - if (!(curenv->env_pgdir[PDX(bottom)] & PTE_P)) { - cprintf("[%08x] Tried to print unmapped address\n", curenv->env_id); - env_destroy(curenv); - return; - } - - pde_t pgdir_allowed = curenv->env_pgdir[PDX(bottom)] & PTE_U; - pde_t pt_allowed = *pgdir_walk(curenv->env_pgdir, bottom, 0) & PTE_U; - if(((curenv->env_tf.tf_cs & 0b11) > 1) && !(pt_allowed & pgdir_allowed)) { - cprintf("[%08x] Tried to print forbidden memory\n", curenv->env_id); - env_destroy(curenv); - return; - } - - bottom += PGSIZE; - } - + user_mem_assert(curenv, s, len, 0); // Print the string supplied by the user. cprintf("%.*s", len, s); }