[CRIU] [PATCH 3/3] seccomp: Use BUG after CR_STATE_RESTORE_SIGCHLD stage if failed

Andrey Vagin avagin at virtuozzo.com
Fri May 25 00:45:43 MSK 2018


On Thu, May 24, 2018 at 11:54:59AM +0300, Cyrill Gorcunov wrote:
> 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 at gmail.com>
> ---
>  criu/pie/restorer.c | 31 ++++++++++++++++++++++++++++---
>  1 file changed, 28 insertions(+), 3 deletions(-)
> 
> 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;

Why do you move this check after switching a stage?
> +
>  	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))

I don't think that we need this check and BUG. I think when one thread
calls BUG(), the whole process will be killed.

> +		BUG();
> +
>  	if (args->check_only) {
>  		pr_info("Restore check was successful.\n");
>  		while (1) {
> -- 
> 2.14.3
> 


More information about the CRIU mailing list