[12/28] seccomp: Untaggle entries from process_tree

Submitted by Cyrill Gorcunov on March 20, 2018, 9:42 p.m.

Details

Message ID 20180320214313.25326-13-gorcunov@gmail.com
State Rejected
Series "seccomp, v2: Add support for per-thread tracking"
Headers show

Commit Message

Cyrill Gorcunov March 20, 2018, 9:42 p.m.
From: Cyrill Gorcunov <gorcunov@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@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(-)

Patch hide | download patch | download mbox

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;