[CRIU] [PATCH 2/2] lsm: restore lsm bits per tid instead of per pid

Tycho Andersen tycho.andersen at canonical.com
Mon Jun 8 13:12:27 PDT 2015


This is a little tricky, since the threads are forked in the restorer blob, we
can't open their attr/curent files to pass into the restorer blob. So, we pass
in an fd for /proc that the restorer blob can use to access the attr/current
files once they exist.

N.B. this is still incorrect in that it restores the same credentials for all
threads in the group; however, it matches the behavior of the current creds
restore code, which also restores the same creds for all threads in the group.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 cr-restore.c       | 24 +++++++--------
 include/restorer.h |  9 ++++--
 pie/restorer.c     | 85 +++++++++++++++++++++++++++++++++++++-----------------
 3 files changed, 76 insertions(+), 42 deletions(-)

diff --git a/cr-restore.c b/cr-restore.c
index aa00dc2..95254e7 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -2823,6 +2823,14 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 
 		strncpy(lsm, rendered, lsm_profile_len);
 		xfree(rendered);
+
+		task_args->proc_fd = dup(get_service_fd(PROC_FD_OFF));
+		if (task_args->proc_fd < 0) {
+			pr_perror("can't dup proc fd");
+			goto err;
+		}
+	} else {
+		task_args->proc_fd = -1;
 	}
 
 	/*
@@ -2879,18 +2887,10 @@ static int sigreturn_restore(pid_t pid, CoreEntry *core)
 	else
 		task_args->helpers = NULL;
 
-	if (lsm) {
-		task_args->proc_attr_current = open_proc_rw(PROC_SELF, "attr/current");
-		if (task_args->proc_attr_current < 0) {
-			pr_perror("Can't open attr/current");
-			goto err;
-		}
-
-		task_args->lsm_profile = rst_mem_remap_ptr(lsm_pos, RM_PRIVATE);
-		task_args->lsm_profile_len = lsm_profile_len;
-	} else {
-		task_args->lsm_profile = NULL;
-	}
+	if (lsm)
+		task_args->creds.lsm_profile = rst_mem_remap_ptr(lsm_pos, RM_PRIVATE);
+	else
+		task_args->creds.lsm_profile = NULL;
 
 	/*
 	 * Arguments for task restoration.
diff --git a/include/restorer.h b/include/restorer.h
index 34396e3..d0a9ce4 100644
--- a/include/restorer.h
+++ b/include/restorer.h
@@ -154,9 +154,12 @@ struct task_restore_args {
 	pid_t				*helpers /* the TASK_HELPERS to wait on at the end of restore */;
 	int				n_helpers;
 
-	int				proc_attr_current;
-	char				*lsm_profile;
-	int				lsm_profile_len;
+	/*
+	 * proc_fd is a handle to /proc that the restorer blob can use to open
+	 * files there, because some of them can't be opened before the
+	 * restorer blob is called.
+	 */
+	int				proc_fd;
 
 #ifdef CONFIG_VDSO
 	unsigned long			vdso_rt_size;
diff --git a/pie/restorer.c b/pie/restorer.c
index 8713c6a..e4a19dc 100644
--- a/pie/restorer.c
+++ b/pie/restorer.c
@@ -95,7 +95,59 @@ static void sigchld_handler(int signal, siginfo_t *siginfo, void *data)
 	sys_exit_group(1);
 }
 
-static int restore_creds(CredsEntry *ce)
+static void pie_strcat(char *dest, char *src)
+{
+	char *p;
+	int off;
+
+	for (p = dest; *p; p++)
+		;
+
+	off = p - dest;
+
+	for (p = src; *p; p++)
+		dest[off + p - src] = *p;
+
+	dest[off + p - src] = 0;
+}
+
+static int lsm_set_label(char *label, int procfd)
+{
+	int ret = -1, len, lsmfd;
+	char path[80] = "self/task/", num[12], *n;
+
+	if (!label)
+		return 0;
+
+	pr_info("restoring lsm profile %s\n", label);
+
+	num[sizeof(num) - 1] = 0;
+	len = vprint_num(num, sizeof(num) - 1, sys_gettid(), &n);
+	pie_strcat(path, n);
+
+	pie_strcat(path, "/attr/current");
+
+	lsmfd = sys_openat(procfd, path, O_WRONLY, 0);
+	sys_close(procfd);
+	if (lsmfd < 0) {
+		pr_err("failed openat %d\n", lsmfd);
+		return -1;
+	}
+
+	for (len = 0; label[len]; len++)
+		;
+
+	ret = sys_write(lsmfd, label, len);
+	sys_close(lsmfd);
+	if (ret < 0) {
+		pr_err("can't write lsm profile %d\n", ret);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int restore_creds(CredsEntry *ce, int procfd)
 {
 	int b, i, ret;
 	struct cap_header hdr;
@@ -200,6 +252,9 @@ static int restore_creds(CredsEntry *ce)
 		return -1;
 	}
 
+	if (lsm_set_label(ce->lsm_profile, procfd) < 0)
+		return -1;
+
 	return 0;
 }
 
@@ -366,7 +421,7 @@ long __export_restore_thread(struct thread_restore_args *args)
 	if (restore_thread_common(rt_sigframe, args))
 		goto core_restore_end;
 
-	ret = restore_creds(&args->ta->creds);
+	ret = restore_creds(&args->ta->creds, args->ta->proc_fd);
 	if (ret)
 		goto core_restore_end;
 
@@ -740,25 +795,6 @@ static int wait_helpers(struct task_restore_args *task_args)
 	return 0;
 }
 
-static int lsm_set_label(struct task_restore_args *args)
-{
-	int ret = -1;
-
-	if (!args->lsm_profile)
-		return 0;
-
-	pr_info("restoring lsm profile %s\n", args->lsm_profile);
-
-	ret = sys_write(args->proc_attr_current, args->lsm_profile, args->lsm_profile_len);
-	sys_close(args->proc_attr_current);
-	if (ret < 0) {
-		pr_err("can't write lsm profile\n");
-		return -1;
-	}
-
-	return ret;
-}
-
 /*
  * The main routine to restore task via sigreturn.
  * This one is very special, we never return there
@@ -1175,15 +1211,10 @@ long __export_restore_task(struct task_restore_args *args)
 	 * thus restore* creds _after_ all of the above.
 	 */
 
-	ret = restore_creds(&args->creds);
+	ret = restore_creds(&args->creds, args->proc_fd);
 	ret = ret || restore_dumpable_flag(&args->mm);
 	ret = ret || restore_pdeath_sig(args->t);
 
-	if (lsm_set_label(args) < 0) {
-		pr_err("lsm_set_label failed\n");
-		goto core_restore_end;
-	}
-
 	futex_set_and_wake(&thread_inprogress, args->nr_threads);
 
 	restore_finish_stage(CR_STATE_RESTORE_CREDS);
-- 
2.1.4



More information about the CRIU mailing list