Add validate_user_string helper function to validate that a string is fully conatined within user vm
This commit is contained in:
@@ -46,6 +46,7 @@ static void syscall_close (int fd);
|
||||
|
||||
static struct open_file *fd_get_file (int fd);
|
||||
static void validate_user_pointer (const void *start, size_t size);
|
||||
static void validate_user_string (const char *str);
|
||||
|
||||
/* A struct defining a syscall_function pointer along with its arity. */
|
||||
typedef struct
|
||||
@@ -140,7 +141,7 @@ syscall_exit (int status)
|
||||
static pid_t
|
||||
syscall_exec (const char *cmd_line)
|
||||
{
|
||||
validate_user_pointer (cmd_line, 1);
|
||||
validate_user_string (cmd_line);
|
||||
|
||||
pid_t pid = process_execute(cmd_line);
|
||||
|
||||
@@ -159,9 +160,9 @@ syscall_wait (pid_t pid)
|
||||
pointer. Acquires the file system lock to prevent synchronisation issues,
|
||||
and then uses FILESYS_CREATE to create the file, returning the same status */
|
||||
static bool
|
||||
syscall_create (const char *file UNUSED, unsigned initial_size UNUSED)
|
||||
syscall_create (const char *file, unsigned initial_size)
|
||||
{
|
||||
validate_user_pointer (file, 1);
|
||||
validate_user_string (file);
|
||||
|
||||
lock_acquire (&filesys_lock);
|
||||
bool status = filesys_create (file, initial_size);
|
||||
@@ -176,7 +177,7 @@ syscall_create (const char *file UNUSED, unsigned initial_size UNUSED)
|
||||
static bool
|
||||
syscall_remove (const char *file)
|
||||
{
|
||||
validate_user_pointer (file, 1);
|
||||
validate_user_string (file);
|
||||
|
||||
lock_acquire (&filesys_lock);
|
||||
bool status = filesys_remove (file);
|
||||
@@ -192,7 +193,7 @@ syscall_remove (const char *file)
|
||||
static int
|
||||
syscall_open (const char *file)
|
||||
{
|
||||
validate_user_pointer (file, 1);
|
||||
validate_user_string (file);
|
||||
|
||||
lock_acquire (&filesys_lock);
|
||||
struct file *ptr = filesys_open (file);
|
||||
@@ -418,3 +419,37 @@ validate_user_pointer (const void *start, size_t size)
|
||||
if (pagedir_get_page (thread_current ()->pagedir, ptr) == NULL)
|
||||
thread_exit ();
|
||||
}
|
||||
|
||||
/* Validates if a string is fully contained within user virtual memory. Kills
|
||||
the thread (by calling thread_exit) if the memory is invalid. Otherwise,
|
||||
returns (nothing) normally. */
|
||||
static void
|
||||
validate_user_string (const char *str)
|
||||
{
|
||||
if (str == NULL || !is_user_vaddr (str))
|
||||
thread_exit ();
|
||||
|
||||
size_t length = 0;
|
||||
size_t offset = (uintptr_t) str % PGSIZE;
|
||||
|
||||
/* We move page by page, checking if the page is mapped to physical memory. */
|
||||
for (;;)
|
||||
{
|
||||
void *page = pg_round_down (str + length);
|
||||
|
||||
if (!is_user_vaddr(page) ||
|
||||
pagedir_get_page (thread_current ()->pagedir, page) == NULL)
|
||||
thread_exit ();
|
||||
|
||||
while (offset < PGSIZE)
|
||||
{
|
||||
if (*str == '\0')
|
||||
return; /* We reached the end of the string without issues. */
|
||||
|
||||
str++;
|
||||
offset++;
|
||||
}
|
||||
|
||||
offset = 0; /* Next page will start at the beginning. */
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user