From e94c85fe6e91058349fbca65ad8e9d278bf8e938 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Fri, 2 Mar 2012 19:28:13 +0400 Subject: [PATCH] restorer: Fix bootstrap allocation There are three bugs in this code. 1. self vmas list is released before get-hint is called 2. get-hint code wrongly detects the hole (just bugs, no details) 3. exec hint is mapped without MAP_FIXED, but should Signed-off-by: Pavel Emelyanov Signed-off-by: Cyrill Gorcunov --- cr-restore.c | 44 +++++++++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index 5c164fd11..11c2c4640 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1512,16 +1512,27 @@ static long restorer_get_vma_hint(pid_t pid, struct list_head *self_vma_list, lo } if ((vma.start - prev_vma_end) > vma_len) { + unsigned long prev_vma_end2 = 0; + list_for_each_entry(vma_area, self_vma_list, list) { - if (vma_area->vma.start <= prev_vma_end && - vma_area->vma.end >= prev_vma_end) - break; + if (!prev_vma_end2) { + prev_vma_end2 = vma_area->vma.end; + continue; + } + + if ((prev_vma_end2 >= prev_vma_end2) && + (vma_area->vma.start - prev_vma_end2) > vma_len) { + hint = prev_vma_end2; + goto found; + } + + prev_vma_end2 = vma_area->vma.end; } - hint = prev_vma_end; - break; - } else - prev_vma_end = vma.end; + } + + prev_vma_end = vma.end; } +found: close_safe(&fd); return hint; } @@ -1700,8 +1711,6 @@ static void sigreturn_restore(pid_t pid) num++; } - free_mappings(&self_vma_list); - restore_code_len = sizeof(restorer_blob); restore_code_len = round_up(restore_code_len, 16); @@ -1735,18 +1744,19 @@ static void sigreturn_restore(pid_t pid) pr_err("No suitable area for task_restore bootstrap (%ldK)\n", restore_task_vma_len + restore_thread_vma_len); goto err; - } else { - pr_info("Found bootstrap VMA hint at: %lx (needs ~%ldK)\n", - exec_mem_hint, - KBYTES(restore_task_vma_len + restore_thread_vma_len)); } + pr_info("Found bootstrap VMA hint at: %lx (needs ~%ldK)\n", exec_mem_hint, + KBYTES(restore_task_vma_len + restore_thread_vma_len)); + + free_mappings(&self_vma_list); + /* VMA we need to run task_restore code */ exec_mem = mmap((void *)exec_mem_hint, restore_task_vma_len + restore_thread_vma_len, PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_PRIVATE | MAP_ANON, 0, 0); - if (exec_mem == MAP_FAILED) { + MAP_PRIVATE | MAP_ANON | MAP_FIXED, 0, 0); + if (exec_mem != (void *)exec_mem_hint) { pr_err("Can't mmap section for restore code\n"); goto err; } @@ -1784,7 +1794,7 @@ static void sigreturn_restore(pid_t pid) * but this area is taken into account for 'hint' memory * address. */ - shmems_ref = (struct shmems *)(exec_mem_hint + + shmems_ref = (struct shmems *)(exec_mem + restore_task_vma_len + restore_thread_vma_len); ret = shmem_remap(shmems, shmems_ref, SHMEMS_SIZE); @@ -1792,7 +1802,7 @@ static void sigreturn_restore(pid_t pid) goto err; task_args->shmems = shmems_ref; - shmems_ref = (struct shmems *)(exec_mem_hint + + shmems_ref = (struct shmems *)(exec_mem + restore_task_vma_len + restore_thread_vma_len + SHMEMS_SIZE);