diff --git a/src/userprog/syscall.c b/src/userprog/syscall.c index 9d2521a..9ddd6e9 100644 --- a/src/userprog/syscall.c +++ b/src/userprog/syscall.c @@ -45,7 +45,7 @@ static unsigned syscall_tell (int fd); static void syscall_close (int fd); static struct open_file *fd_get_file (int fd); -static void validate_user_pointer (const void *ptr, size_t size); +static void validate_user_pointer (const void *start, size_t size); /* A struct defining a syscall_function pointer along with its arity. */ typedef struct @@ -397,16 +397,24 @@ fd_get_file (int fd) return hash_entry (e, struct open_file, elem); } -/* Validates if a block of memory starting at PTR and of size SIZE bytes is +/* Validates if a block of memory starting at START and of size SIZE bytes is fully contained within user virtual memory. Kills the thread (by calling - thread_exit) if the memory is invalid. Otherwise, returns the PTR given. - If the size is 0, the function does no checks and returns PTR.*/ + thread_exit) if the memory is invalid. Otherwise, returns (nothing) normally. + If the size is 0, the function does no checks and returns the given ptr. */ static void -validate_user_pointer (const void *ptr, size_t size) +validate_user_pointer (const void *start, size_t size) { - if (size > 0 && (ptr == NULL || - !is_user_vaddr (ptr) || - !is_user_vaddr (ptr + size - 1) || - pagedir_get_page (thread_current()->pagedir, ptr) == NULL)) + if (size == 0) + return; + + const void *end = start + size - 1; + + if (start == NULL || !is_user_vaddr (start) || !is_user_vaddr (end)) thread_exit (); + + /* We now need to check if the entire memory block is mapped to physical + memory by the page table. */ + for (const void *ptr = start; ptr <= end; ptr += PGSIZE) + if (pagedir_get_page (thread_current ()->pagedir, ptr) == NULL) + thread_exit (); }