Implement complete stack initialization for user processes, without accounting for overflow
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user