Can't clear page tables on exec()
Posted: Sun Apr 02, 2017 7:41 pm
Hello,
My paging implementation is largely based on James Molloy's tutorials, and I'm trying to figure out how to clear all page tables of a page directory created from clone_directory() upon exec().
clone_directory()'s implementation can be seen here: http://www.jamesmolloy.co.uk/tutorial_h ... aging.html
I've tried as follows. I'm immediately trying to wipe all page tables in the parent after a fork() for testing purposes; once this works I'll incorporate it into the exec() implementation. The problem I'm having is if I try to clear all page tables, I immediately triple fault. This is avoided if I don't clear any kernel tables, but that leaves me with the same result as clone_directory(), and defeats the purpose in the first place.
My paging implementation is largely based on James Molloy's tutorials, and I'm trying to figure out how to clear all page tables of a page directory created from clone_directory() upon exec().
clone_directory()'s implementation can be seen here: http://www.jamesmolloy.co.uk/tutorial_h ... aging.html
I've tried as follows. I'm immediately trying to wipe all page tables in the parent after a fork() for testing purposes; once this works I'll incorporate it into the exec() implementation. The problem I'm having is if I try to clear all page tables, I immediately triple fault. This is avoided if I don't clear any kernel tables, but that leaves me with the same result as clone_directory(), and defeats the purpose in the first place.
Code: Select all
int pid = sys_fork();
//block child as we wipe its page directory
//strictly for prototyping
block_task(task_with_pid(pid), ZOMBIE);
if (!pid) {
//asm stub which places arg in ebx and calls int 0x80 (syscall vector)
sys__exit(0xdeadbeef);
}
else {
task_t* child = task_with_pid(pid);
uint32_t eip_addr = child->eip;
page_directory_t* old = child->page_dir;
//for each page table in page directory
for (int i = 0; i < 1024; i++) {
page_table_t* tab = old->tables[i];
//find page table containing this address
uint32_t instruction_table_idx = (eip_addr / 0x1000) / 1024;
if (i == instruction_table_idx) {
//skip clearing page table containing code we want to execute when the child runs
continue;
}
//for each page in page table
for (int j = 0; j < 1024; j++) {
//skip unassigned pages
if (!tab->pages[j].frame) continue;
//many crashes if this is removed
//don't remove any pages which were linked directly from the kernel
extern page_directory_t* kernel_directory;
if (tab->pages[j].frame == kernel_directory->tables[i]->pages[j].frame) {
continue;
}
free_frame(&(tab->pages[j]));
tab->pages[j].present = 0;
}
}
sleep(3000);
unblock_task(child);
int stat;
waitpid(pid, &stat, NULL);
printf("Child exited with status %x\n", stat);
while (1) {}