[CRIU] [PATCH 12/28] seccomp: Untaggle entries from process_tree
Cyrill Gorcunov
gorcunov at gmail.com
Wed Mar 21 00:42:57 MSK 2018
From: Cyrill Gorcunov <gorcunov at virtuozzo.com>
When dumping threads we need to be able to lookup
seccomps based on tid only, so make seccomp engine
to not depend on pstree item.
Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
---
criu/cr-dump.c | 4 ++-
criu/include/pstree.h | 2 --
criu/include/seccomp.h | 8 ++++--
criu/pstree.c | 1 -
criu/seccomp.c | 78 ++++++++++++++++++++++++++++++++++----------------
criu/seize.c | 8 +++---
6 files changed, 66 insertions(+), 35 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 7aabd4736905..dc3fb5f6a8ff 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -759,7 +759,7 @@ static int dump_task_core_all(struct parasite_ctl *ctl,
if (ret < 0)
goto err;
- entry = seccomp_find_entry(item, pid);
+ entry = seccomp_find_entry(pid);
if (!entry) {
ret = -1;
goto err;
@@ -1622,6 +1622,7 @@ static int cr_pre_dump_finish(int ret)
}
free_pstree(root_item);
+ seccomp_free_entries();
if (irmap_predump_run()) {
ret = -1;
@@ -1831,6 +1832,7 @@ static int cr_dump_finish(int ret)
TASK_ALIVE : opts.final_state);
timing_stop(TIME_FROZEN);
free_pstree(root_item);
+ seccomp_free_entries();
free_file_locks();
free_link_remaps();
free_aufs_branches();
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index e7922cfaa5b9..105237b1eaae 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -60,8 +60,6 @@ static inline struct rst_info *rsti(struct pstree_item *i)
struct ns_id;
struct dmp_info {
struct ns_id *netns;
- struct seccomp_entry *seccomp_entry;
- size_t nr_seccomp_entry;
unsigned int last_filter;
struct page_pipe *mem_pp;
struct parasite_ctl *parasite_ctl;
diff --git a/criu/include/seccomp.h b/criu/include/seccomp.h
index 7e38ee2ea7fd..63ab0cf9dcf2 100644
--- a/criu/include/seccomp.h
+++ b/criu/include/seccomp.h
@@ -28,15 +28,19 @@
#endif
struct pstree_item;
+struct rb_node;
struct seccomp_entry {
+ struct rb_node node;
pid_t tid_real;
size_t last_filter;
unsigned int mode;
};
-extern struct seccomp_entry *seccomp_find_entry(const struct pstree_item *item, pid_t tid_real);
-extern int seccomp_collect_entry(const struct pstree_item *item, pid_t tid_real, unsigned int mode);
+extern struct seccomp_entry *seccomp_lookup(pid_t tid_real, bool create, bool mandatory);
+#define seccomp_find_entry(tid_real) seccomp_lookup(tid_real, false, true)
+extern int seccomp_collect_entry(pid_t tid_real, unsigned int mode);
+extern void seccomp_free_entries(void);
struct seccomp_info {
struct seccomp_info *prev;
diff --git a/criu/pstree.c b/criu/pstree.c
index cd887418c80b..10bf54410b98 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -192,7 +192,6 @@ void free_pstree_item(struct pstree_item *item)
{
pstree_free_cores(item);
xfree(item->threads);
- xfree(dmpi(item)->seccomp_entry);
xfree(item->pid);
xfree(item->pgid);
xfree(item->sid);
diff --git a/criu/seccomp.c b/criu/seccomp.c
index 4256f8d2ca12..dab7b2ed4c80 100644
--- a/criu/seccomp.c
+++ b/criu/seccomp.c
@@ -21,44 +21,72 @@
#undef LOG_PREFIX
#define LOG_PREFIX "seccomp: "
-struct seccomp_entry *seccomp_find_entry(const struct pstree_item *item, pid_t tid_real)
+static struct rb_root seccomp_tid_rb_root = RB_ROOT;
+
+struct seccomp_entry *seccomp_lookup(pid_t tid_real, bool create, bool mandatory)
{
- struct dmp_info *dinfo = dmpi(item);
- size_t i;
+ struct seccomp_entry *entry = NULL;
+
+ struct rb_node *node = seccomp_tid_rb_root.rb_node;
+ struct rb_node **new = &seccomp_tid_rb_root.rb_node;
+ struct rb_node *parent = NULL;
+
+ while (node) {
+ struct seccomp_entry *this = rb_entry(node, struct seccomp_entry, node);
+
+ parent = *new;
+ if (tid_real < this->tid_real)
+ node = node->rb_left, new = &((*new)->rb_left);
+ else if (tid_real > this->tid_real)
+ node = node->rb_right, new = &((*new)->rb_right);
+ else
+ return this;
+ }
- for (i = 0; i < dinfo->nr_seccomp_entry; i++) {
- if (dinfo->seccomp_entry[i].tid_real == tid_real)
- return &dinfo->seccomp_entry[i];
+ if (create) {
+ entry = xzalloc(sizeof(*entry));
+ if (!entry)
+ return NULL;
+ rb_init_node(&entry->node);
+ entry->tid_real = tid_real;
+
+ rb_link_and_balance(&seccomp_tid_rb_root, &entry->node, parent, new);
+ } else {
+ if (mandatory)
+ pr_err("Can't find entry on tid_real %d\n", tid_real);
}
- pr_err("Can't find entry on pid_real %d tid_real %d (%zu entries)\n",
- item->pid->real, tid_real, dinfo->nr_seccomp_entry);
- return NULL;
+ return entry;
}
-int seccomp_collect_entry(const struct pstree_item *item, pid_t tid_real, unsigned int mode)
+int seccomp_collect_entry(pid_t tid_real, unsigned int mode)
{
- struct dmp_info *dinfo = dmpi(item);
struct seccomp_entry *entry;
- size_t new_size;
- new_size = sizeof(*dinfo->seccomp_entry) * (dinfo->nr_seccomp_entry + 1);
- if (xrealloc_safe(&dinfo->seccomp_entry, new_size)) {
- pr_err("Can't collect seccomp entry for item %d tid_real %d\n",
- item->pid->real, tid_real);
- return -ENOMEM;
+ entry = seccomp_lookup(tid_real, true, false);
+ if (!entry) {
+ pr_err("Can't create entry on tid_real %d\n", tid_real);
+ return -1;
}
- entry = &dinfo->seccomp_entry[dinfo->nr_seccomp_entry];
- entry->tid_real = tid_real;
- entry->mode = mode;
+ entry->mode = mode;
- dinfo->nr_seccomp_entry++;
- pr_debug("Collected tid_real %d mode %#x (%zu entries)\n",
- tid_real, mode, dinfo->nr_seccomp_entry);
+ pr_debug("Collected tid_real %d mode %#x\n", tid_real, mode);
return 0;
}
+void seccomp_free_entries(void)
+{
+ struct seccomp_entry *entry;
+ struct rb_node *node;
+
+ while ((node = rb_first(&seccomp_tid_rb_root))) {
+ rb_erase(node, &seccomp_tid_rb_root);
+ entry = rb_entry(node, struct seccomp_entry, node);
+ xfree(entry);
+ }
+}
+
/* populated on dump during collect_seccomp_filters() */
static int next_filter_id = 0;
static struct seccomp_info **filters = NULL;
@@ -101,7 +129,7 @@ static int collect_filter_for_pstree(struct pstree_item *item)
if (item->pid->state == TASK_DEAD)
return 0;
- entry = seccomp_find_entry(item, item->pid->real);
+ entry = seccomp_find_entry(item->pid->real);
if (!entry)
return -1;
if (entry->mode != SECCOMP_MODE_FILTER)
@@ -139,7 +167,7 @@ static int collect_filter_for_pstree(struct pstree_item *item)
}
}
- entry_parent = seccomp_find_entry(item->parent, item->parent->pid->real);
+ entry_parent = seccomp_find_entry(item->parent->pid->real);
if (!entry_parent)
goto out;
inherited = find_inherited(entry_parent->last_filter, buf, len, meta);
diff --git a/criu/seize.c b/criu/seize.c
index 2223ab27e362..5dfbab277581 100644
--- a/criu/seize.c
+++ b/criu/seize.c
@@ -514,7 +514,7 @@ static int collect_children(struct pstree_item *item)
c->pid->state = ret;
list_add_tail(&c->sibling, &item->children);
- ret = seccomp_collect_entry(c, pid, creds.s.seccomp_mode);
+ ret = seccomp_collect_entry(pid, creds.s.seccomp_mode);
if (ret < 0)
goto free;
@@ -640,7 +640,7 @@ static int collect_threads(struct pstree_item *item)
int nr_threads = 0, i = 0, j, ret, nr_inprogress, nr_stopped = 0;
int level = item->pid->level, id;
- task_seccomp_entry = seccomp_find_entry(item, item->pid->real);
+ task_seccomp_entry = seccomp_find_entry(item->pid->real);
if (!task_seccomp_entry)
goto err;
@@ -724,7 +724,7 @@ static int collect_threads(struct pstree_item *item)
goto err;
}
- if (seccomp_collect_entry(item, pid, t_creds.s.seccomp_mode))
+ if (seccomp_collect_entry(pid, t_creds.s.seccomp_mode))
goto err;
if (task_seccomp_entry->mode != t_creds.s.seccomp_mode) {
@@ -856,7 +856,7 @@ int collect_pstree(void)
pr_info("Seized task %d, state %d\n", pid, ret);
root_item->pid->state = ret;
- ret = seccomp_collect_entry(root_item, pid, creds.s.seccomp_mode);
+ ret = seccomp_collect_entry(pid, creds.s.seccomp_mode);
if (ret < 0)
goto err;
--
2.14.3
More information about the CRIU
mailing list