From 6c6ce77824b5a9338e59d2fcf24c9bc3e2059146 Mon Sep 17 00:00:00 2001 From: Themis Demetriades Date: Mon, 4 Nov 2024 01:11:19 +0000 Subject: [PATCH] Implement complete stack initialization for user processes, without accounting for overflow --- src/userprog/process.c | 44 +++++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 7 deletions(-) diff --git a/src/userprog/process.c b/src/userprog/process.c index 452f020..7b6ebe9 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -58,6 +58,14 @@ process_execute (const char *file_name) return tid; } +static void * +push_to_stack (void **esp, void *data, size_t data_size) +{ + *esp -= data_size; + memcpy (*esp, data, data_size); + return *esp; +} + /* A thread function that loads a user process and starts it running. */ static void @@ -70,27 +78,32 @@ start_process (void *file_name_) of the process. */ char *saveptr; char *arg = strtok_r (file_name_, " ", &saveptr); + + char file_name[15]; + strlcpy (file_name, arg, 15); /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.cs = SEL_UCSEG; if_.eflags = FLAG_IF | FLAG_MBS; - success = load (arg, &if_.eip, &if_.esp); + success = load (file_name, &if_.eip, &if_.esp); /* Load command line argument *data* to user process stack. This can't cause overflow due to enforcing that the size of command line input must fit in a page. Also keep track of pointers to the argument data within a linked list. */ + char *file_name_ptr = push_to_stack (&if_.esp, file_name, + (strlen (file_name) + 1) + * sizeof (char)); + struct list arg_list; list_init (&arg_list); - unsigned int arg_count = 1; + int arg_count = 1; while (arg != NULL) { - size_t arg_size = (strlen (arg) + 1) * sizeof (char); - if_.esp -= arg_size; - memcpy (if_.esp, arg, arg_size); + push_to_stack (&if_.esp, arg, (strlen (arg) + 1) * sizeof (char)); struct arg_elem *arg_elem = malloc (sizeof (struct arg_elem)); ASSERT (arg_elem != NULL); @@ -122,6 +135,10 @@ start_process (void *file_name_) performance. */ if_.esp -= align_size * sizeof (uint8_t); + /* Push a null pointer sentinel inside argv. */ + if_.esp -= sizeof (char *); + *(char *) if_.esp = NULL; + /* Push pointers to process arguments from argument linked list */ struct list_elem *e = list_begin (&arg_list); struct list_elem *tail = list_tail (&arg_list); @@ -129,13 +146,26 @@ start_process (void *file_name_) { struct arg_elem *arg_elem = list_entry (e, struct arg_elem, elem); - if_.esp -= sizeof (char *); - memcpy (if_.esp, arg_elem->arg, sizeof (char *)); + push_to_stack (&if_.esp, &arg_elem->arg, sizeof (arg_elem->arg)); e = list_next (e); free (arg_elem); } + /* Push pointer to the process file name to the stack. */ + char **argv = push_to_stack (&if_.esp, &file_name_ptr, + sizeof (file_name_ptr)); + + /* Push pointer to the start of argv array. */ + push_to_stack (&if_.esp, &argv, sizeof(argv)); + + /* Push the number of arguments to the stack. */ + push_to_stack (&if_.esp, &arg_count, sizeof (arg_count)); + + /* Push fake return address (null pointer). */ + if_.esp -= sizeof (char *); + *(char *) if_.esp = NULL; + /* If load failed, quit. */ palloc_free_page (file_name_); if (!success)