[CRIU] [PATCH v2 7/9] lsm: change when LSM profiles are collected

Tycho Andersen tycho.andersen at canonical.com
Mon Oct 24 08:51:11 PDT 2016


Instead of collecting profiles right at thread dump time, let's collect
them all at a single point. This way, when we add support for suspending
LSMs, we know what profiles if any we need to suspend.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 criu/cr-dump.c        | 12 +++++++++---
 criu/include/lsm.h    |  6 ++----
 criu/include/pstree.h |  6 ++++++
 criu/lsm.c            | 44 ++++++++++++++++++++++++++++++++++++++------
 4 files changed, 55 insertions(+), 13 deletions(-)

diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 360bfcc..e2410b8 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -669,9 +669,7 @@ int dump_thread_core(int pid, CoreEntry *core, bool native, const void *dump_thr
 	int ret;
 	ThreadCoreEntry *tc = core->thread_core;
 
-	ret = collect_lsm_profile(pid, tc->creds);
-	if (!ret)
-		ret = get_task_futex_robust_list(pid, tc);
+	ret = get_task_futex_robust_list(pid, tc);
 	if (!ret)
 		ret = dump_sched_info(pid, tc);
 	if (!ret) {
@@ -742,6 +740,8 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
 	core->tc->task_state = item->pid.state;
 	core->tc->exit_code = 0;
 
+	core->thread_core->creds->lsm_profile = dmpi(item)->thread_lsms[0];
+
 	ret = parasite_dump_thread_leader_seized(ctl, pid, core);
 	if (ret)
 		goto err;
@@ -847,6 +847,8 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
 	}
 	pstree_insert_pid(tid->virt, tid);
 
+	core->thread_core->creds->lsm_profile = dmpi(item)->thread_lsms[id];
+
 	img = open_image(CR_FD_CORE, O_DUMP, tid->virt);
 	if (!img)
 		goto err;
@@ -1660,6 +1662,7 @@ static int cr_dump_finish(int ret)
 	 *    start rollback procedure and cleanup everyhting.
 	 */
 	if (ret || post_dump_ret || opts.final_state == TASK_ALIVE) {
+		unsuspend_lsm();
 		network_unlock();
 		delete_link_remaps();
 		clean_cr_time_mounts();
@@ -1779,6 +1782,9 @@ int cr_dump_tasks(pid_t pid)
 	if (collect_seccomp_filters() < 0)
 		goto err;
 
+	if (collect_and_suspend_lsm() < 0)
+		goto err;
+
 	for_each_pstree_item(item) {
 		if (dump_one_task(item))
 			goto err;
diff --git a/criu/include/lsm.h b/criu/include/lsm.h
index 554d150..8092696 100644
--- a/criu/include/lsm.h
+++ b/criu/include/lsm.h
@@ -16,10 +16,8 @@ extern Lsmtype host_lsm_type(void);
  */
 extern void kerndat_lsm(void);
 
-/*
- * Read the LSM profile for the pstree item
- */
-extern int collect_lsm_profile(pid_t, CredsEntry *);
+int collect_and_suspend_lsm(void);
+int unsuspend_lsm(void);
 
 /*
  * Render the profile name in the way that the LSM wants it written to
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index 5768b64..e4a0d70 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -45,6 +45,12 @@ struct dmp_info {
 	struct proc_status_creds *pi_creds;
 	struct page_pipe *mem_pp;
 	struct parasite_ctl *parasite_ctl;
+
+	/* Although we don't support dumping different struct creds in general,
+	 * we do for threads. Let's keep track of their profiles here; a NULL
+	 * entry means there was no LSM profile for this thread.
+	 */
+	char **thread_lsms;
 };
 
 static inline struct dmp_info *dmpi(const struct pstree_item *i)
diff --git a/criu/lsm.c b/criu/lsm.c
index 39f13a3..4510201 100644
--- a/criu/lsm.c
+++ b/criu/lsm.c
@@ -150,23 +150,55 @@ Lsmtype host_lsm_type(void)
 	return lsmtype;
 }
 
-int collect_lsm_profile(pid_t pid, CredsEntry *ce)
+static int collect_lsm_profile(pid_t pid, char **profile)
 {
-	ce->lsm_profile = NULL;
+	*profile = NULL;
 
 	if (lsmtype == LSMTYPE__NO_LSM)
 		return 0;
 
-	if (get_label(pid, &ce->lsm_profile) < 0)
+	if (get_label(pid, profile) < 0)
 		return -1;
 
-	if (lsmtype == LSMTYPE__APPARMOR && collect_aa_namespace(ce->lsm_profile) < 0) {
+	if (lsmtype == LSMTYPE__APPARMOR && collect_aa_namespace(*profile) < 0) {
 		pr_err("failed to collect AA namespace\n");
 		return -1;
 	}
 
-	if (ce->lsm_profile)
-		pr_info("%d has lsm profile %s\n", pid, ce->lsm_profile);
+	if (*profile)
+		pr_info("%d has lsm profile %s\n", pid, *profile);
+
+	return 0;
+}
+
+int collect_and_suspend_lsm(void)
+{
+	struct pstree_item *item;
+
+	for_each_pstree_item(item) {
+		int i;
+
+		dmpi(item)->thread_lsms = xmalloc(item->nr_threads * sizeof(char));
+		if (!dmpi(item)->thread_lsms)
+			return -1;
+
+		for (i = 0; i < item->nr_threads; i++) {
+			if (collect_lsm_profile(item->threads[i].real, &dmpi(item)->thread_lsms[i]) < 0)
+				return -1;
+		}
+	}
+
+	/* now, suspend the LSM */
+	switch(lsmtype) {
+	default:
+		pr_warn("don't know how to suspend LSM %d\n", lsmtype);
+	}
+
+	return 0;
+}
+
+int unsuspend_lsm(void)
+{
 
 	return 0;
 }
-- 
2.9.3



More information about the CRIU mailing list