[CRIU] [PATCH v4 1/7] lsm: change when LSM profiles are collected
Tycho Andersen
tycho.andersen at canonical.com
Thu Oct 27 15:54:55 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.
v2: allocate thread_lsms as the right size to avoid memory corruption
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 | 42 +++++++++++++++++++++++++++++++++++++-----
4 files changed, 54 insertions(+), 12 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 955ba97..7707b8c 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -667,9 +667,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) {
@@ -740,6 +738,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;
@@ -845,6 +845,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;
@@ -1658,6 +1660,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();
@@ -1777,6 +1780,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 b97195e..47e6d2e 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);
/*
* Validate that the LSM profiles can be correctly applied (must happen after
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 27ca004..ff51fae 100644
--- a/criu/lsm.c
+++ b/criu/lsm.c
@@ -148,22 +148,54 @@ 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 (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(dmpi(item)->thread_lsms[0]));
+ 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; this is where code that implements something
+ * like PTRACE_O_SUSPEND_LSM should live. */
+ switch(lsmtype) {
+ default:
+ pr_warn("don't know how to suspend LSM %d\n", lsmtype);
+ }
+
+ return 0;
+}
+
+int unsuspend_lsm(void)
+{
+ return 0;
+}
+
// in inventory.c
extern Lsmtype image_lsm;
--
2.9.3
More information about the CRIU
mailing list