From 97bfd3bb9b5b730dc9258343b2dbce92e012f3b6 Mon Sep 17 00:00:00 2001 From: Bahadir Balban Date: Fri, 1 May 2009 22:39:31 +0300 Subject: [PATCH] Fixed error escalation in thread_create() and its function calls. --- src/api/thread.c | 21 +++++++++++++++++---- src/arch/arm/v5/mm.c | 22 ++++++++++++++++++++-- src/generic/pgalloc.c | 6 +++++- tasks/test0/main.c | 2 +- 4 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/api/thread.c b/src/api/thread.c index 4306009..a2eb1de 100644 --- a/src/api/thread.c +++ b/src/api/thread.c @@ -265,23 +265,36 @@ int thread_setup_new_ids(struct task_ids *ids, unsigned int flags, */ int thread_create(struct task_ids *ids, unsigned int flags) { - struct ktcb *task = 0, *new = (struct ktcb *)zalloc_page(); + struct ktcb *task = 0; + struct ktcb *new = (struct ktcb *)zalloc_page(); unsigned int create_flags = flags & THREAD_CREATE_MASK; + if (!new) + return -ENOMEM; + /* Determine space allocation */ if (create_flags == THREAD_NEW_SPACE) { /* Allocate new pgd and copy all kernel areas */ - new->pgd = alloc_pgd(); + if (!(new->pgd = alloc_pgd())) { + free_page(new); + return -ENOMEM; + } + copy_pgd_kern_all(new->pgd); } else { /* Existing space will be used, find it from all tasks */ list_for_each_entry(task, &global_task_list, task_list) { /* Space ids match, can use existing space */ if (task->spid == ids->spid) { - if (flags == THREAD_SAME_SPACE) + if (flags == THREAD_SAME_SPACE) { new->pgd = task->pgd; - else + } else { new->pgd = copy_page_tables(task->pgd); + if (IS_ERR(new->pgd)) { + free_page(new); + return (int)new->pgd; + } + } goto out; } } diff --git a/src/arch/arm/v5/mm.c b/src/arch/arm/v5/mm.c index fb48d82..8250162 100644 --- a/src/arch/arm/v5/mm.c +++ b/src/arch/arm/v5/mm.c @@ -6,6 +6,7 @@ #include #include #include +#include #include INC_SUBARCH(mm.h) #include INC_SUBARCH(mmu_ops.h) #include INC_GLUE(memory.h) @@ -428,7 +429,9 @@ pgd_table_t *copy_page_tables(pgd_table_t *from) pgd_table_t *pgd; /* Allocate and copy pgd. This includes all kernel entries */ - pgd = alloc_pgd(); + if (!(pgd = alloc_pgd())) + return PTR_ERR(-ENOMEM); + memcpy(pgd, from, sizeof(pgd_table_t)); /* Allocate and copy all pmds that will be exclusive to new task. */ @@ -437,7 +440,8 @@ pgd_table_t *copy_page_tables(pgd_table_t *from) if (!is_kern_pgdi(i) && ((pgd->entry[i] & PGD_TYPE_MASK) == PGD_TYPE_COARSE)) { /* Allocate new pmd */ - pmd = alloc_pmd(); + if (!(pmd = alloc_pmd())) + goto out_error; /* Find original pmd */ orig = (pmd_table_t *) @@ -454,6 +458,20 @@ pgd_table_t *copy_page_tables(pgd_table_t *from) } return pgd; + +out_error: + /* Find all allocated pmds and free them */ + for (int i = 0; i < PGD_ENTRY_TOTAL; i++) { + if ((pgd->entry[i] & PGD_TYPE_MASK) == PGD_TYPE_COARSE) { + /* Clear coarse indicator from address */ + pgd->entry[i] &= ~PGD_TYPE_COARSE; + /* Free pmd by converting to its virtual value first */ + free_pmd((void *)phys_to_virt(pgd->entry[i])); + } + } + /* Free the pgd */ + free_pgd(pgd); + return PTR_ERR(-ENOMEM); } extern pmd_table_t *pmd_array; diff --git a/src/generic/pgalloc.c b/src/generic/pgalloc.c index 872650f..ade5e0a 100644 --- a/src/generic/pgalloc.c +++ b/src/generic/pgalloc.c @@ -181,7 +181,11 @@ int free_pgd(void *v) void *zalloc_page(void) { - void *p = alloc_page(); + void *p; + + if (!(p = alloc_page())) + return 0; + memset(p, 0, PAGE_SIZE); return p; } diff --git a/tasks/test0/main.c b/tasks/test0/main.c index 260a227..04847c2 100644 --- a/tasks/test0/main.c +++ b/tasks/test0/main.c @@ -33,7 +33,7 @@ void main(void) dirtest(); - // exectest(); + exectest(); /* Check mmap/munmap */ mmaptest();