diff options
Diffstat (limited to 'kernel/pid_namespace.c')
| -rw-r--r-- | kernel/pid_namespace.c | 22 | 
1 files changed, 22 insertions, 0 deletions
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index f4f8cb0435b4..46e0d5a3f91f 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -23,6 +23,7 @@  #include <linux/sched/task.h>  #include <linux/sched/signal.h>  #include <linux/idr.h> +#include "pid_sysctl.h"  static DEFINE_MUTEX(pid_caches_mutex);  static struct kmem_cache *pid_ns_cachep; @@ -110,6 +111,8 @@ static struct pid_namespace *create_pid_namespace(struct user_namespace *user_ns  	ns->ucounts = ucounts;  	ns->pid_allocated = PIDNS_ADDING; +	initialize_memfd_noexec_scope(ns); +  	return ns;  out_free_idr: @@ -244,7 +247,24 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)  		set_current_state(TASK_INTERRUPTIBLE);  		if (pid_ns->pid_allocated == init_pids)  			break; +		/* +		 * Release tasks_rcu_exit_srcu to avoid following deadlock: +		 * +		 * 1) TASK A unshare(CLONE_NEWPID) +		 * 2) TASK A fork() twice -> TASK B (child reaper for new ns) +		 *    and TASK C +		 * 3) TASK B exits, kills TASK C, waits for TASK A to reap it +		 * 4) TASK A calls synchronize_rcu_tasks() +		 *                   -> synchronize_srcu(tasks_rcu_exit_srcu) +		 * 5) *DEADLOCK* +		 * +		 * It is considered safe to release tasks_rcu_exit_srcu here +		 * because we assume the current task can not be concurrently +		 * reaped at this point. +		 */ +		exit_tasks_rcu_stop();  		schedule(); +		exit_tasks_rcu_start();  	}  	__set_current_state(TASK_RUNNING); @@ -455,6 +475,8 @@ static __init int pid_namespaces_init(void)  #ifdef CONFIG_CHECKPOINT_RESTORE  	register_sysctl_paths(kern_path, pid_ns_ctl_table);  #endif + +	register_pid_ns_sysctl_table_vm();  	return 0;  }  | 
