Implement VM #63

Merged
td1223 merged 94 commits from vm/merged/themis into master 2024-12-06 05:07:14 +00:00
28 changed files with 293 additions and 868 deletions
Showing only changes of commit 9a6abab95e - Show all commits

View File

@@ -47,7 +47,8 @@ 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 *ptr, size_t size,
bool check_write);
static int get_user (const uint8_t *);
static bool put_user (uint8_t *, uint8_t);
@@ -99,8 +100,8 @@ static void
syscall_handler (struct intr_frame *f)
{
/* First, read the system call number from the stack. */
validate_user_pointer (f->esp, 1);
unsigned syscall_number = *(int *) f->esp;
validate_user_pointer (f->esp, 1, false);
unsigned syscall_number = *(int *)f->esp;
/* Ensures the number corresponds to a system call that can be handled. */
if (syscall_number >= LOOKUP_SIZE)
@@ -110,10 +111,10 @@ syscall_handler (struct intr_frame *f)
/* Next, read and copy the arguments from the stack pointer. */
validate_user_pointer (f->esp + sizeof (uintptr_t),
syscall.arity * sizeof (uintptr_t));
uintptr_t args[3] = {0};
for (int i=0; i < syscall.arity; i++)
args[i] = *(uintptr_t *) (f->esp + sizeof (uintptr_t) * (i + 1));
syscall.arity * sizeof (uintptr_t), false);
uintptr_t args[3] = { 0 };
for (int i = 0; i < syscall.arity; i++)
args[i] = *(uintptr_t *)(f->esp + sizeof (uintptr_t) * (i + 1));
/* Call the function that handles this system call with the arguments. When
there is a return value it is stored in f->eax. */
@@ -144,7 +145,7 @@ syscall_exit (int status)
static pid_t
syscall_exec (const char *cmd_line)
{
validate_user_pointer (cmd_line, 1);
validate_user_pointer (cmd_line, 1, false);
lock_acquire (&filesys_lock);
pid_t pid = process_execute(cmd_line);
@@ -167,7 +168,7 @@ syscall_wait (pid_t pid)
static bool
syscall_create (const char *file UNUSED, unsigned initial_size UNUSED)
{
validate_user_pointer (file, 1);
validate_user_pointer (file, 1, false);
lock_acquire (&filesys_lock);
bool status = filesys_create (file, initial_size);
@@ -182,7 +183,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_pointer (file, 1, false);
lock_acquire (&filesys_lock);
bool status = filesys_remove (file);
@@ -198,7 +199,7 @@ syscall_remove (const char *file)
static int
syscall_open (const char *file)
{
validate_user_pointer (file, 1);
validate_user_pointer (file, 1, false);
lock_acquire (&filesys_lock);
struct file *ptr = filesys_open (file);
@@ -253,7 +254,7 @@ syscall_read (int fd, void *buffer, unsigned size)
if (fd < 0 || fd == STDOUT_FILENO)
return -1;
validate_user_pointer (buffer, size);
validate_user_pointer (buffer, size, true);
if (fd == STDIN_FILENO)
{
@@ -290,7 +291,7 @@ syscall_write (int fd, const void *buffer, unsigned size)
if (fd <= 0)
return 0;
validate_user_pointer (buffer, size);
validate_user_pointer (buffer, size, false);
if (fd == STDOUT_FILENO)
{
@@ -404,19 +405,26 @@ fd_get_file (int fd)
}
/* Validates if a block of memory starting at PTR 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.
fully contained within user virtual memory. Returns NULL if the memory
is invalid. Otherwise, returns the PTR given.
If the size is 0, the function does no checks and returns PTR.*/
static void *
validate_user_pointer (const void *ptr, size_t size)
validate_user_pointer (const void *ptr, size_t size, bool check_write)
{
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 ptr;
/* ptr < ptr + size - 1, so sufficient to check that (ptr + size -1) is a
valid user virtual memory address. */
if (!is_user_vaddr (ptr + size - 1))
thread_exit ();
return (void *) ptr;
/* Check read access to pointer. */
int result;
if ((result = get_user (ptr)) == -1)
thread_exit ();
/* Check write access to pointer (if required). */
if (check_write && !put_user (ptr, result))
thread_exit ();
return ptr;
}
/* PROVIDED BY SPEC.