[CRIU] [PATCH] restore: handle errors of setting credentials (v2)

Andrey Vagin avagin at openvz.org
Tue Apr 23 16:16:44 EDT 2013


v2: handle errors from setXids and securebits manipulations
    handle errors of restoring creds after finishing CR_STATE_RESTORE_CREDS,
    because a sigchild handler is already restored in this moment.
    Only the current process is killed in a error case.

Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 cr-restore.c       | 12 +++++++++
 include/restorer.h |  1 +
 pie/restorer.c     | 71 +++++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 72 insertions(+), 12 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index f1cb706..d9f074b 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -56,6 +56,7 @@
 #include "cpu.h"
 #include "file-lock.h"
 #include "page-read.h"
+#include "sysctl.h"
 
 #include "protobuf.h"
 #include "protobuf/sa.pb-c.h"
@@ -1464,6 +1465,17 @@ static int prepare_creds(int pid, struct task_restore_core_args *args)
 	int fd, ret;
 	CredsEntry *ce;
 
+	struct sysctl_req req[] = {
+		{ "kernel/cap_last_cap", &args->cap_last_cap, CTL_U32 },
+		{ },
+	};
+
+	ret = sysctl_op(req, CTL_READ);
+	if (ret < 0) {
+		pr_err("Failed to read max IPC message size\n");
+		return -1;
+	}
+
 	fd = open_image(CR_FD_CREDS, O_RSTR, pid);
 	if (fd < 0)
 		return fd;
diff --git a/include/restorer.h b/include/restorer.h
index ef19d64..6a9da84 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -120,6 +120,7 @@ struct task_restore_core_args {
 	uint32_t			cap_prm[CR_CAP_SIZE];
 	uint32_t			cap_eff[CR_CAP_SIZE];
 	uint32_t			cap_bnd[CR_CAP_SIZE];
+	uint32_t			cap_last_cap;
 
 	MmEntry				mm;
 	auxv_t				mm_saved_auxv[AT_VECTOR_SIZE];
diff --git a/pie/restorer.c b/pie/restorer.c
index 4feea0c..b92b54d 100644
--- a/pie/restorer.c
+++ b/pie/restorer.c
@@ -40,6 +40,7 @@
 static struct task_entries *task_entries;
 static futex_t thread_inprogress;
 static futex_t zombies_inprogress;
+static int cap_last_cap;
 
 extern void cr_restore_rt (void) asm ("__cr_restore_rt")
 			__attribute__ ((visibility ("hidden")));
@@ -74,9 +75,9 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 	sys_exit_group(1);
 }
 
-static void restore_creds(CredsEntry *ce)
+static int restore_creds(CredsEntry *ce)
 {
-	int b, i;
+	int b, i, ret;
 	struct cap_header hdr;
 	struct cap_data data[_LINUX_CAPABILITY_U32S_3];
 
@@ -89,7 +90,11 @@ static void restore_creds(CredsEntry *ce)
 	 * lose caps bits when changing xids.
 	 */
 
-	sys_prctl(PR_SET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP, 0, 0, 0);
+	ret = sys_prctl(PR_SET_SECUREBITS, 1 << SECURE_NO_SETUID_FIXUP, 0, 0, 0);
+	if (ret) {
+		pr_err("Unable to set SECURE_NO_SETUID_FIXUP: %d\n", ret);
+		return -1;
+	}
 
 	/*
 	 * Second -- restore xids. Since we still have the CAP_SETUID
@@ -97,17 +102,40 @@ static void restore_creds(CredsEntry *ce)
 	 * to override the setresXid settings.
 	 */
 
-	sys_setresuid(ce->uid, ce->euid, ce->suid);
+	ret = sys_setresuid(ce->uid, ce->euid, ce->suid);
+	if (ret) {
+		pr_err("Unable to set real, effective and saved user ID: %d\n", ret);
+		return -1;
+	}
+
 	sys_setfsuid(ce->fsuid);
-	sys_setresgid(ce->gid, ce->egid, ce->sgid);
+	if (sys_setfsuid(-1) != ce->fsuid) {
+		pr_err("Unable to set fsuid\n");
+		return -1;
+	}
+
+	ret = sys_setresgid(ce->gid, ce->egid, ce->sgid);
+	if (ret) {
+		pr_err("Unable to set real, effective and saved group ID: %d\n", ret);
+		return -1;
+	}
+
 	sys_setfsgid(ce->fsgid);
+	if (sys_setfsgid(-1) != ce->fsgid) {
+		pr_err("Unable to set fsgid\n");
+		return -1;
+	}
 
 	/*
 	 * Third -- restore securebits. We don't need them in any
 	 * special state any longer.
 	 */
 
-	sys_prctl(PR_SET_SECUREBITS, ce->secbits, 0, 0, 0);
+	ret = sys_prctl(PR_SET_SECUREBITS, ce->secbits, 0, 0, 0);
+	if (ret) {
+		pr_err("Unable to set PR_SET_SECUREBITS: %d\n", ret);
+		return -1;
+	}
 
 	/*
 	 * Fourth -- trim bset. This can only be done while
@@ -116,11 +144,17 @@ static void restore_creds(CredsEntry *ce)
 
 	for (b = 0; b < CR_CAP_SIZE; b++) {
 		for (i = 0; i < 32; i++) {
+			if (b * 32 + i > cap_last_cap)
+				break;
 			if (ce->cap_bnd[b] & (1 << i))
 				/* already set */
 				continue;
-
-			sys_prctl(PR_CAPBSET_DROP, i + b * 32, 0, 0, 0);
+			ret = sys_prctl(PR_CAPBSET_DROP, i + b * 32, 0, 0, 0);
+			if (ret) {
+				pr_err("Unable to drop capability %d: %d\n",
+								i + b * 32, ret);
+				return -1;
+			}
 		}
 	}
 
@@ -140,7 +174,13 @@ static void restore_creds(CredsEntry *ce)
 		data[i].inh = ce->cap_inh[i];
 	}
 
-	sys_capset(&hdr, data);
+	ret = sys_capset(&hdr, data);
+	if (ret) {
+		pr_err("Unable to restore capabilities: %d\n", ret);
+		return -1;
+	}
+
+	return 0;
 }
 
 static void restore_sched_info(struct rst_sched_param *p)
@@ -242,6 +282,7 @@ long __export_restore_thread(struct thread_restore_args *args)
 	struct rt_sigframe *rt_sigframe;
 	unsigned long new_sp;
 	int my_pid = sys_gettid();
+	int ret;
 
 	if (my_pid != args->pid) {
 		pr_err("Thread pid mismatch %d/%d\n", my_pid, args->pid);
@@ -255,8 +296,9 @@ long __export_restore_thread(struct thread_restore_args *args)
 
 	mutex_unlock(&args->ta->rst_lock);
 
-	restore_creds(&args->ta->creds);
-
+	ret = restore_creds(&args->ta->creds);
+	if (ret)
+		goto core_restore_end;
 
 	pr_info("%ld: Restored\n", sys_gettid());
 
@@ -466,6 +508,8 @@ long __export_restore_task(struct task_restore_core_args *args)
 	log_set_fd(args->logfd);
 	log_set_loglevel(args->loglevel);
 
+	cap_last_cap = args->cap_last_cap;
+
 	pr_info("Switched to the restorer %d\n", my_pid);
 
 	for (vma_entry = args->self_vmas; vma_entry->start != 0; vma_entry++) {
@@ -778,12 +822,15 @@ long __export_restore_task(struct task_restore_core_args *args)
 	 * thus restore* creds _after_ all of the above.
 	 */
 
-	restore_creds(&args->creds);
+	ret = restore_creds(&args->creds);
 
 	futex_set_and_wake(&thread_inprogress, args->nr_threads);
 
 	restore_finish_stage(CR_STATE_RESTORE_CREDS);
 
+	if (ret)
+		BUG();
+
 	/* Wait until children stop to use args->task_entries */
 	futex_wait_while_gt(&thread_inprogress, 1);
 
-- 
1.8.2



More information about the CRIU mailing list