[1/1] seccomp: Use BUG after CR_STATE_RESTORE_SIGCHLD stage if failed

Submitted by Cyrill Gorcunov on May 23, 2018, 4:09 p.m.

Details

Message ID 20180523160907.31856-2-gorcunov@gmail.com
State Rejected
Series "A few fixes for seccomp code"
Headers show

Commit Message

Cyrill Gorcunov May 23, 2018, 4:09 p.m.
As avagin@ pointed we can't use exit after CR_STATE_RESTORE_SIGCHLD
stage, thus simply remember if we've failed and kill everything
when triggered.

Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
---
 criu/pie/restorer.c | 31 ++++++++++++++++++++++++++++---
 1 file changed, 28 insertions(+), 3 deletions(-)

Patch hide | download patch | download mbox

diff --git a/criu/pie/restorer.c b/criu/pie/restorer.c
index fbdec0bca01c..b9dca5e99af7 100644
--- a/criu/pie/restorer.c
+++ b/criu/pie/restorer.c
@@ -66,6 +66,7 @@ 
 	})
 
 static struct task_entries *task_entries_local;
+static atomic_t thread_aborted = ATOMIC_INIT(0);
 static futex_t thread_inprogress;
 static pid_t *helpers;
 static int n_helpers;
@@ -588,18 +589,23 @@  long __export_restore_thread(struct thread_restore_args *args)
 	 * operation bound to uid 0 in current user ns.
 	 */
 	if (restore_seccomp(args))
-		goto core_restore_end;
+		goto thread_panic;
 
 	ret = restore_creds(args->creds_args, args->ta->proc_fd);
 	ret = ret || restore_dumpable_flag(&args->ta->mm);
 	ret = ret || restore_pdeath_sig(args);
-	if (ret)
-		goto core_restore_end;
 
 	restore_finish_stage(task_entries_local, CR_STATE_RESTORE_CREDS);
 
 	futex_dec_and_wake(&thread_inprogress);
 
+	/*
+	 * We can't just exit in such deep stage on thread restore,
+	 * instead notify group leader that we've failed.
+	 */
+	if (ret)
+		goto thread_panic;
+
 	if (check_only)
 		restore_finish_stage(task_entries_local, CR_STATE_COMPLETE);
 
@@ -611,6 +617,11 @@  long __export_restore_thread(struct thread_restore_args *args)
 	futex_abort_and_wake(&task_entries_local->nr_in_progress);
 	sys_exit_group(1);
 	return -1;
+thread_panic:
+	pr_err("Restorer panic for %ld\n", sys_getpid());
+	atomic_set(&thread_aborted, 1);
+	BUG();
+	return -1;
 }
 
 static long restore_self_exe_late(struct task_restore_args *args)
@@ -1748,6 +1759,20 @@  long __export_restore_task(struct task_restore_args *args)
 	/* Wait until children stop to use args->task_entries */
 	futex_wait_while_gt(&thread_inprogress, 1);
 
+	/*
+	 * If error happened somewhere insidee deep restore of
+	 * a thread where we can't exit gracefully and have fired
+	 * BUG already, do the same here in group leader so all
+	 * threads get killed as well.
+	 *
+	 * Note that we've to complete @thread_inprogress counting
+	 * since the group leader is still waiting and futex-abort
+	 * flag won't work here because the form we have futexes
+	 * doesn't allow multiple writers
+	 */
+	if (atomic_read(&thread_aborted))
+		BUG();
+
 	if (args->check_only) {
 		pr_info("Restore check was successful.\n");
 		while (1) {