[CRIU] [PATCH] rst: Fix creds vs threads restoration

Pavel Emelyanov xemul at parallels.com
Tue Oct 30 02:37:17 EDT 2012


Writing to last_pid sysctl is CAP_SYS_ADMIN potected. Thus restoring
creds before it won't work in all the cases.

Fix this by making all threads restore creds themselves, and the
thread group leader -- after all of them.

#2410

Signed-off-by: Pavel Emelyanov <xemul at parallels.com>

---

diff --git a/cr-restore.c b/cr-restore.c
index e930b49..d47e34f 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -1495,7 +1495,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
 	if (ret < 0)
 		goto err;
 
-	mutex_init(&task_args->t._rst_lock);
+	mutex_init(&task_args->rst_lock);
 
 	/*
 	 * Now prepare run-time data for threads restore.
@@ -1537,7 +1537,7 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core, struct list_head *tgt_v
 			goto err;
 		}
 
-		thread_args[i].rst_lock		= &task_args->t._rst_lock;
+		thread_args[i].ta		= task_args;
 		thread_args[i].gpregs		= *core->thread_info->gpregs;
 		thread_args[i].clear_tid_addr	= core->thread_info->clear_tid_addr;
 
diff --git a/include/restorer.h b/include/restorer.h
index 7c74a29..11750e4 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -62,6 +62,8 @@ struct rst_sched_param {
 	int prio;
 };
 
+struct task_restore_core_args;
+
 /* Make sure it's pow2 in size */
 struct thread_restore_args {
 	struct restore_mem_zone		mem_zone;
@@ -76,10 +78,7 @@ struct thread_restore_args {
 
 	struct rst_sched_param		sp;
 
-	union {
-		mutex_t			_rst_lock;
-		mutex_t			*rst_lock;
-	};
+	struct task_restore_core_args	*ta;
 } __aligned(sizeof(long));
 
 struct task_restore_core_args {
@@ -90,6 +89,8 @@ struct task_restore_core_args {
 	int				logfd;
 	unsigned int			loglevel;
 
+	mutex_t				rst_lock;
+
 	/* threads restoration */
 	int				nr_threads;		/* number of threads */
 	thread_restore_fcall_t		clone_restore_fn;	/* helper address for clone() call */
diff --git a/restorer.c b/restorer.c
index 2dd3733..369adb9 100644
--- a/restorer.c
+++ b/restorer.c
@@ -224,7 +224,9 @@ long __export_restore_thread(struct thread_restore_args *args)
 	if (restore_thread_common(rt_sigframe, args))
 		goto core_restore_end;
 
-	mutex_unlock(args->rst_lock);
+	mutex_unlock(&args->ta->rst_lock);
+
+	restore_creds(&args->ta->creds);
 
 	futex_dec_and_wake(&task_entries->nr_in_progress);
 
@@ -529,14 +531,6 @@ long __export_restore_task(struct task_restore_core_args *args)
 			goto core_restore_end;
 		}
 
-		/* 
-		 * last-pid is CAP_SYS_ADMIN protected, thus restore creds
-		 * _after_ opening that file, but before fork to make threads
-		 * inherit them properly
-		 */
-
-		restore_creds(&args->creds);
-
 		ret = sys_flock(fd, LOCK_EX);
 		if (ret) {
 			pr_err("Can't lock last_pid %d\n", fd);
@@ -550,7 +544,7 @@ long __export_restore_task(struct task_restore_core_args *args)
 			if (thread_args[i].pid == args->t.pid)
 				continue;
 
-			mutex_lock(&args->t._rst_lock);
+			mutex_lock(&args->rst_lock);
 
 			new_sp =
 				RESTORE_ALIGN_STACK((long)thread_args[i].mem_zone.stack,
@@ -613,8 +607,14 @@ long __export_restore_task(struct task_restore_core_args *args)
 		}
 
 		sys_close(fd);
-	} else
-		restore_creds(&args->creds);
+	}
+
+	/* 
+	 * Writing to last-pid is CAP_SYS_ADMIN protected, thus restore
+	 * creds _after_ all threads creation.
+	 */
+
+	restore_creds(&args->creds);
 
 	futex_dec_and_wake(&args->task_entries->nr_in_progress);
 


More information about the CRIU mailing list