Implement complete stack initialization for user processes, without accounting for overflow

This commit is contained in:
Themis Demetriades
2024-11-04 01:11:19 +00:00
parent 6f9c911ebe
commit 6c6ce77824

View File

@@ -58,6 +58,14 @@ process_execute (const char *file_name)
return tid; 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 /* A thread function that loads a user process and starts it
running. */ running. */
static void static void
@@ -70,27 +78,32 @@ start_process (void *file_name_)
of the process. */ of the process. */
char *saveptr; char *saveptr;
char *arg = strtok_r (file_name_, " ", &saveptr); char *arg = strtok_r (file_name_, " ", &saveptr);
char file_name[15];
strlcpy (file_name, arg, 15);
/* Initialize interrupt frame and load executable. */ /* Initialize interrupt frame and load executable. */
memset (&if_, 0, sizeof if_); memset (&if_, 0, sizeof if_);
if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG; if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
if_.cs = SEL_UCSEG; if_.cs = SEL_UCSEG;
if_.eflags = FLAG_IF | FLAG_MBS; 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. /* Load command line argument *data* to user process stack.
This can't cause overflow due to enforcing that the size of This can't cause overflow due to enforcing that the size of
command line input must fit in a page. Also keep track command line input must fit in a page. Also keep track
of pointers to the argument data within a linked list. */ 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; struct list arg_list;
list_init (&arg_list); list_init (&arg_list);
unsigned int arg_count = 1; int arg_count = 1;
while (arg != NULL) while (arg != NULL)
{ {
size_t arg_size = (strlen (arg) + 1) * sizeof (char); push_to_stack (&if_.esp, arg, (strlen (arg) + 1) * sizeof (char));
if_.esp -= arg_size;
memcpy (if_.esp, arg, arg_size);
struct arg_elem *arg_elem = malloc (sizeof (struct arg_elem)); struct arg_elem *arg_elem = malloc (sizeof (struct arg_elem));
ASSERT (arg_elem != NULL); ASSERT (arg_elem != NULL);
@@ -122,6 +135,10 @@ start_process (void *file_name_)
performance. */ performance. */
if_.esp -= align_size * sizeof (uint8_t); 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 */ /* Push pointers to process arguments from argument linked list */
struct list_elem *e = list_begin (&arg_list); struct list_elem *e = list_begin (&arg_list);
struct list_elem *tail = list_tail (&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); struct arg_elem *arg_elem = list_entry (e, struct arg_elem, elem);
if_.esp -= sizeof (char *); push_to_stack (&if_.esp, &arg_elem->arg, sizeof (arg_elem->arg));
memcpy (if_.esp, arg_elem->arg, sizeof (char *));
e = list_next (e); e = list_next (e);
free (arg_elem); 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. */ /* If load failed, quit. */
palloc_free_page (file_name_); palloc_free_page (file_name_);
if (!success) if (!success)