Feat: pointer validation checks string across multiple pages and handle kernel page faults

This commit is contained in:
EDiasAlberto
2024-11-29 23:49:49 +00:00
parent 5f40d83e66
commit 5c661c2e24
4 changed files with 37 additions and 27 deletions

View File

@@ -143,9 +143,7 @@ struct thread
struct hash open_files; /* Hash Table of FD -> Struct File. */ struct hash open_files; /* Hash Table of FD -> Struct File. */
#endif #endif
#ifdef VM
void *curr_esp; void *curr_esp;
#endif
/* Owned by thread.c. */ /* Owned by thread.c. */
unsigned magic; /* Detects stack overflow. */ unsigned magic; /* Detects stack overflow. */

View File

@@ -1,7 +1,7 @@
# -*- makefile -*- # -*- makefile -*-
kernel.bin: DEFINES = -DUSERPROG -DFILESYS kernel.bin: DEFINES = -DUSERPROG -DFILESYS -DVM
KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys KERNEL_SUBDIRS = threads devices lib lib/kernel userprog filesys vm
TEST_SUBDIRS = tests/userprog tests/userprog/no-vm tests/filesys/base TEST_SUBDIRS = tests/userprog tests/userprog/no-vm tests/filesys/base
GRADING_FILE = $(SRCDIR)/tests/userprog/Grading GRADING_FILE = $(SRCDIR)/tests/userprog/Grading
SIMULATOR = --qemu SIMULATOR = --qemu

View File

@@ -146,19 +146,19 @@ page_fault (struct intr_frame *f)
write = (f->error_code & PF_W) != 0; write = (f->error_code & PF_W) != 0;
user = (f->error_code & PF_U) != 0; user = (f->error_code & PF_U) != 0;
/* Kernel page fault is further handled by the kernel itself. */ if (user && not_present)
if (kernel)
{ {
f->eip = (void *)f->eax; if (try_alloc_new_page (fault_addr, f->esp))
return;
}
else
{
if (try_alloc_new_page (fault_addr, thread_current ()->curr_esp))
return;
f->eip = (void *)f->eax;
f->eax = 0xffffffff; f->eax = 0xffffffff;
return; return;
} }
if (user)
{
if (try_alloc_new_page (fault_addr, f->esp))
return;
}
/* To implement virtual memory, delete the rest of the function /* To implement virtual memory, delete the rest of the function
body, and replace it with code that brings in the page to body, and replace it with code that brings in the page to

View File

@@ -10,9 +10,6 @@
#include "threads/synch.h" #include "threads/synch.h"
#include "userprog/process.h" #include "userprog/process.h"
#include "userprog/pagedir.h" #include "userprog/pagedir.h"
#ifdef VM
#include "vm/stackgrowth.h"
#endif
#include <stdio.h> #include <stdio.h>
#include <stdbool.h> #include <stdbool.h>
#include <syscall-nr.h> #include <syscall-nr.h>
@@ -465,17 +462,17 @@ validate_user_pointer (const void *ptr, size_t size, bool check_write)
valid user virtual memory address. */ valid user virtual memory address. */
void *last = ptr + size - 1; void *last = ptr + size - 1;
if (!is_user_vaddr (last)) if (!is_user_vaddr (last))
thread_exit (); syscall_exit (EXIT_FAILURE);
ptr = pg_round_down (ptr); ptr = pg_round_down (ptr);
while (ptr <= last) while (ptr <= last)
{ {
int result; int result;
/* Check read access to pointer. */ /* Check read access to pointer. */
if ((result = get_user (ptr)) == -1) if ((result = get_user (ptr)) == -1)
thread_exit (); syscall_exit (EXIT_FAILURE);
/* Check write access to pointer (if required). */ /* Check write access to pointer (if required). */
if (check_write && !put_user (ptr, result)) if (check_write && !put_user (ptr, result))
thread_exit (); syscall_exit (EXIT_FAILURE);
ptr += PGSIZE; ptr += PGSIZE;
} }
} }
@@ -485,18 +482,33 @@ validate_user_pointer (const void *ptr, size_t size, bool check_write)
static void static void
validate_user_string (const char *ptr, bool check_write) validate_user_string (const char *ptr, bool check_write)
{ {
while (true) size_t offset = (uintptr_t) ptr % PGSIZE;
for (;;)
{ {
void *page = pg_round_down (ptr);
if (!is_user_vaddr (page))
syscall_exit (EXIT_FAILURE);
if (!is_user_vaddr (ptr)) if (!is_user_vaddr (ptr))
thread_exit (); syscall_exit (EXIT_FAILURE);
int result; int result;
if ((result = get_user ((const uint8_t *)ptr)) == -1) if ((result = get_user ((const uint8_t *)ptr)) == -1)
thread_exit (); syscall_exit (EXIT_FAILURE);
if (check_write && !put_user ((uint8_t *)ptr, result)) if (check_write && !put_user ((uint8_t *)ptr, result))
thread_exit (); syscall_exit (EXIT_FAILURE);
if (*ptr == '\0')
return; while (offset < PGSIZE)
ptr++; {
if (*ptr == '\0')
return; /* We reached the end of the string without issues. */
ptr++;
offset++;
}
offset = 0;
} }
} }