X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fuserprog%2Fprocess.c;h=88c9d8dcae20995bb5e7dc3b4b2d5a42ca5b8e6e;hb=251b51f76f0594460e1cfbf2c05576fb445b861b;hp=08e78c683e0024af747573e9fb78e48d63aee4e2;hpb=f0612244c44f4b4f0bc79e3fc882e9f74bd4a3f4;p=pintos-anon diff --git a/src/userprog/process.c b/src/userprog/process.c index 08e78c6..88c9d8d 100644 --- a/src/userprog/process.c +++ b/src/userprog/process.c @@ -31,7 +31,7 @@ process_execute (const char *filename) /* Make a copy of FILENAME. Otherwise there's a race between the caller and load(). */ - fn_copy = palloc_get (0); + fn_copy = palloc_get_page (0); if (fn_copy == NULL) return TID_ERROR; strlcpy (fn_copy, filename, PGSIZE); @@ -39,7 +39,7 @@ process_execute (const char *filename) /* Create a new thread to execute FILENAME. */ tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy); if (tid == TID_ERROR) - palloc_free (fn_copy); + palloc_free_page (fn_copy); return tid; } @@ -54,6 +54,8 @@ execute_thread (void *filename_) /* Initialize interrupt frame and load executable. */ memset (&if_, 0, sizeof if_); + if_.gs = SEL_UDSEG; + if_.fs = SEL_UDSEG; if_.es = SEL_UDSEG; if_.ds = SEL_UDSEG; if_.cs = SEL_UCSEG; @@ -62,7 +64,7 @@ execute_thread (void *filename_) success = load (filename, &if_.eip, &if_.esp); /* If load failed, quit. */ - palloc_free (filename); + palloc_free_page (filename); if (!success) thread_exit (); @@ -71,28 +73,32 @@ execute_thread (void *filename_) /* Start the user process by simulating a return from an interrupt, implemented by intr_exit (in - threads/intr-stubs.pl). Because intr_exit takes all of its + threads/intr-stubs.S). Because intr_exit takes all of its arguments on the stack in the form of a `struct intr_frame', we just point the stack pointer (%esp) to our stack frame and jump to it. */ - asm ("mov %0, %%esp\n" - "jmp intr_exit\n" - : /* no outputs */ - : "g" (&if_)); + asm ("mov %%esp, %0; jmp intr_exit" :: "g" (&if_)); NOT_REACHED (); } -/* Destroys the user address space in T and frees all of its - resources. */ +/* Free the current process's resources. */ void -process_destroy (struct thread *t) +process_exit (void) { - ASSERT (t != thread_current ()); - - if (t->pagedir != NULL) + struct thread *cur = thread_current (); + uint32_t *pd; + + /* Destroy the current process's page directory and switch back + to the kernel-only page directory. We have to set + cur->pagedir to NULL before switching page directories, or a + timer interrupt might switch back to the process page + directory. */ + pd = cur->pagedir; + if (pd != NULL) { - pagedir_destroy (t->pagedir); - t->pagedir = NULL; + cur->pagedir = NULL; + pagedir_activate (NULL); + pagedir_destroy (pd); } } @@ -103,10 +109,11 @@ process_activate (void) { struct thread *t = thread_current (); - /* Activate T's page tables. */ + /* Activate thread's page tables. */ pagedir_activate (t->pagedir); - /* Set T's kernel stack for use in processing interrupts. */ + /* Set thread's kernel stack for use in processing + interrupts. */ tss_set_esp0 ((uint8_t *) t + PGSIZE); } @@ -219,7 +226,7 @@ load (const char *filename, void (**eip) (void), void **esp) if (ehdr.e_machine != 3) LOAD_ERROR (("ELF executable is not x86")); if (ehdr.e_version != 1) - LOAD_ERROR (("ELF executable hasunknown version %d", + LOAD_ERROR (("ELF executable has unknown version %d", (int) ehdr.e_version)); if (ehdr.e_phentsize != sizeof (struct Elf32_Phdr)) LOAD_ERROR (("bad ELF program header size")); @@ -232,7 +239,10 @@ load (const char *filename, void (**eip) (void), void **esp) { struct Elf32_Phdr phdr; + if (file_ofs < 0 || file_ofs > file_length (file)) + LOAD_ERROR (("bad file offset %ld", (long) file_ofs)); file_seek (file, file_ofs); + if (file_read (file, &phdr, sizeof phdr) != sizeof phdr) LOAD_ERROR (("error reading program header")); file_ofs += sizeof phdr; @@ -308,6 +318,13 @@ load_segment (struct file *file, const struct Elf32_Phdr *phdr) return false; } + /* p_offset must point within file. */ + if (phdr->p_offset > (Elf32_Off) file_length (file)) + { + printf ("bad p_offset %"PE32Ox, phdr->p_offset); + return false; + } + /* [ELF1] 2-3 says that p_memsz must be at least as big as p_filesz. */ if (phdr->p_memsz < phdr->p_filesz) @@ -339,14 +356,14 @@ load_segment (struct file *file, const struct Elf32_Phdr *phdr) file into the page and zero the rest. */ size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left; size_t zero_bytes = PGSIZE - read_bytes; - uint8_t *kpage = palloc_get (PAL_USER); + uint8_t *kpage = palloc_get_page (PAL_USER); if (kpage == NULL) return false; /* Do the reading and zeroing. */ if (file_read (file, kpage, read_bytes) != (int) read_bytes) { - palloc_free (kpage); + palloc_free_page (kpage); return false; } memset (kpage + read_bytes, 0, zero_bytes); @@ -355,7 +372,7 @@ load_segment (struct file *file, const struct Elf32_Phdr *phdr) /* Add the page to the process's address space. */ if (!install_page (upage, kpage)) { - palloc_free (kpage); + palloc_free_page (kpage); return false; } } @@ -371,14 +388,14 @@ setup_stack (void **esp) uint8_t *kpage; bool success = false; - kpage = palloc_get (PAL_USER | PAL_ZERO); + kpage = palloc_get_page (PAL_USER | PAL_ZERO); if (kpage != NULL) { success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage); if (success) *esp = PHYS_BASE; else - palloc_free (kpage); + palloc_free_page (kpage); } else printf ("failed to allocate process stack\n");