From e8ac085af8ffe9ee4d840e05e1b6f77add42722d Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Mon, 21 Apr 2014 14:48:05 +0400 Subject: [PATCH] Revert "crtools: close all desriptors only for the root task" We have a race. Consider we have 3 tasks, A, B and C. A and B share fdtable, C -- does not. Then we might be in a situation when A is restoring memory reading mem images, and B -- forking the C child. In that case descriptors held by A (for mem restore) will be inherited by C and will not get closed. This reverts commit d36e07aabe073993d8ae9695e33f6e45b2eb6a21. --- cr-restore.c | 21 +++++++++------------ include/servicefd.h | 1 - util.c | 12 ------------ 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index 584e1dc46..8e07c5652 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -1213,24 +1213,15 @@ static int restore_task_with_children(void *_arg) current->pid.real, current->pid.virt); } + if ( !(ca->clone_flags & CLONE_FILES)) + close_safe(&ca->fd); + if (current->state != TASK_HELPER) { ret = clone_service_fd(current->rst->service_fd_id); if (ret) exit(1); } - if (!(ca->clone_flags & CLONE_FILES)) { - close_safe(&ca->fd); - - if (current->parent && current->parent->rst->fdt) - /* - * We're the first child with our own fdtable of - * a parent which had it shared. From that parent - * we have extra service file descriptors left. - */ - close_old_servie_fd(current->parent->rst->fdt->nr); - } - pid = getpid(); if (current->pid.virt != pid) { pr_err("Pid %d do not match expected %d\n", pid, current->pid.virt); @@ -1286,6 +1277,12 @@ static int restore_task_with_children(void *_arg) if (prepare_mappings(pid)) exit(1); + if (!(ca->clone_flags & CLONE_FILES)) { + ret = close_old_fds(current); + if (ret) + exit(1); + } + if (create_children_and_session()) exit(1); diff --git a/include/servicefd.h b/include/servicefd.h index 451e65e93..89cf3f376 100644 --- a/include/servicefd.h +++ b/include/servicefd.h @@ -26,7 +26,6 @@ extern int get_service_fd(enum sfd_type type); extern int reserve_service_fd(enum sfd_type type); extern int install_service_fd(enum sfd_type type, int fd); extern int close_service_fd(enum sfd_type type); -extern void close_old_servie_fd(int nr); extern bool is_service_fd(int fd, enum sfd_type type); extern bool is_any_service_fd(int fd); diff --git a/util.c b/util.c index 708c84353..81f174166 100644 --- a/util.c +++ b/util.c @@ -341,18 +341,6 @@ int close_service_fd(enum sfd_type type) return 0; } -/* Close all unused service descriptors on a depth of nr. */ -void close_old_servie_fd(int nr) -{ - int level, i; - BUG_ON(service_fd_id != 0); - for (level = 1; level < nr; level++) { - for (i = SERVICE_FD_MIN + 1; i < SERVICE_FD_MAX; i++) { - close(__get_service_fd(i, level)); - } - } -} - int clone_service_fd(int id) { int ret = -1, i;