summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomáš Mózes <hydrapolic@gmail.com>2023-04-14 18:21:01 +0200
committerTomáš Mózes <hydrapolic@gmail.com>2023-04-14 18:21:01 +0200
commit1b2aab0054cd3fe4fd72dad303c3f3b935db42f0 (patch)
tree40cb7bbf1679b605a32469fa3a0da2da6d4143dd /0113-tools-xenstore-add-generic-treewalk-function.patch
parentXen 4.15.4-pre-patchset-2 (diff)
downloadxen-upstream-patches-4.15.tar.gz
xen-upstream-patches-4.15.tar.bz2
xen-upstream-patches-4.15.zip
Xen 4.15.5-pre-patchset-04.15.5-pre-patchset-04.15
Signed-off-by: Tomáš Mózes <hydrapolic@gmail.com>
Diffstat (limited to '0113-tools-xenstore-add-generic-treewalk-function.patch')
-rw-r--r--0113-tools-xenstore-add-generic-treewalk-function.patch250
1 files changed, 0 insertions, 250 deletions
diff --git a/0113-tools-xenstore-add-generic-treewalk-function.patch b/0113-tools-xenstore-add-generic-treewalk-function.patch
deleted file mode 100644
index b80c574..0000000
--- a/0113-tools-xenstore-add-generic-treewalk-function.patch
+++ /dev/null
@@ -1,250 +0,0 @@
-From 83b6c511a5989a83c50daae83c5b5a683d6dc096 Mon Sep 17 00:00:00 2001
-From: Juergen Gross <jgross@suse.com>
-Date: Tue, 13 Sep 2022 07:35:11 +0200
-Subject: [PATCH 113/126] tools/xenstore: add generic treewalk function
-
-Add a generic function to walk the complete node tree. It will start
-at "/" and descend recursively into each child, calling a function
-specified by the caller. Depending on the return value of the user
-specified function the walk will be aborted, continued, or the current
-child will be skipped by not descending into its children.
-
-This is part of XSA-418 / CVE-2022-42321.
-
-Signed-off-by: Juergen Gross <jgross@suse.com>
-Acked-by: Julien Grall <jgrall@amazon.com>
-(cherry picked from commit 0d7c5d19bc27492360196e7dad2b227908564fff)
----
- tools/xenstore/xenstored_core.c | 143 +++++++++++++++++++++++++++++---
- tools/xenstore/xenstored_core.h | 40 +++++++++
- 2 files changed, 170 insertions(+), 13 deletions(-)
-
-diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
-index 4c3897721bdd..7463d0a002d7 100644
---- a/tools/xenstore/xenstored_core.c
-+++ b/tools/xenstore/xenstored_core.c
-@@ -1804,6 +1804,135 @@ static int do_set_perms(const void *ctx, struct connection *conn,
- return 0;
- }
-
-+static char *child_name(const void *ctx, const char *s1, const char *s2)
-+{
-+ if (strcmp(s1, "/"))
-+ return talloc_asprintf(ctx, "%s/%s", s1, s2);
-+ return talloc_asprintf(ctx, "/%s", s2);
-+}
-+
-+static int rm_from_parent(struct connection *conn, struct node *parent,
-+ const char *name)
-+{
-+ size_t off;
-+
-+ if (!parent)
-+ return WALK_TREE_ERROR_STOP;
-+
-+ for (off = parent->childoff - 1; off && parent->children[off - 1];
-+ off--);
-+ if (remove_child_entry(conn, parent, off)) {
-+ log("treewalk: child entry could not be removed from '%s'",
-+ parent->name);
-+ return WALK_TREE_ERROR_STOP;
-+ }
-+ parent->childoff = off;
-+
-+ return WALK_TREE_OK;
-+}
-+
-+static int walk_call_func(const void *ctx, struct connection *conn,
-+ struct node *node, struct node *parent, void *arg,
-+ int (*func)(const void *ctx, struct connection *conn,
-+ struct node *node, void *arg))
-+{
-+ int ret;
-+
-+ if (!func)
-+ return WALK_TREE_OK;
-+
-+ ret = func(ctx, conn, node, arg);
-+ if (ret == WALK_TREE_RM_CHILDENTRY && parent)
-+ ret = rm_from_parent(conn, parent, node->name);
-+
-+ return ret;
-+}
-+
-+int walk_node_tree(const void *ctx, struct connection *conn, const char *root,
-+ struct walk_funcs *funcs, void *arg)
-+{
-+ int ret = 0;
-+ void *tmpctx;
-+ char *name;
-+ struct node *node = NULL;
-+ struct node *parent = NULL;
-+
-+ tmpctx = talloc_new(ctx);
-+ if (!tmpctx) {
-+ errno = ENOMEM;
-+ return WALK_TREE_ERROR_STOP;
-+ }
-+ name = talloc_strdup(tmpctx, root);
-+ if (!name) {
-+ errno = ENOMEM;
-+ talloc_free(tmpctx);
-+ return WALK_TREE_ERROR_STOP;
-+ }
-+
-+ /* Continue the walk until an error is returned. */
-+ while (ret >= 0) {
-+ /* node == NULL possible only for the initial loop iteration. */
-+ if (node) {
-+ /* Go one step up if ret or if last child finished. */
-+ if (ret || node->childoff >= node->childlen) {
-+ parent = node->parent;
-+ /* Call function AFTER processing a node. */
-+ ret = walk_call_func(ctx, conn, node, parent,
-+ arg, funcs->exit);
-+ /* Last node, so exit loop. */
-+ if (!parent)
-+ break;
-+ talloc_free(node);
-+ /* Continue with parent. */
-+ node = parent;
-+ continue;
-+ }
-+ /* Get next child of current node. */
-+ name = child_name(tmpctx, node->name,
-+ node->children + node->childoff);
-+ if (!name) {
-+ ret = WALK_TREE_ERROR_STOP;
-+ break;
-+ }
-+ /* Point to next child. */
-+ node->childoff += strlen(node->children +
-+ node->childoff) + 1;
-+ /* Descent into children. */
-+ parent = node;
-+ }
-+ /* Read next node (root node or next child). */
-+ node = read_node(conn, tmpctx, name);
-+ if (!node) {
-+ /* Child not found - should not happen! */
-+ /* ENOENT case can be handled by supplied function. */
-+ if (errno == ENOENT && funcs->enoent)
-+ ret = funcs->enoent(ctx, conn, parent, name,
-+ arg);
-+ else
-+ ret = WALK_TREE_ERROR_STOP;
-+ if (!parent)
-+ break;
-+ if (ret == WALK_TREE_RM_CHILDENTRY)
-+ ret = rm_from_parent(conn, parent, name);
-+ if (ret < 0)
-+ break;
-+ talloc_free(name);
-+ node = parent;
-+ continue;
-+ }
-+ talloc_free(name);
-+ node->parent = parent;
-+ node->childoff = 0;
-+ /* Call function BEFORE processing a node. */
-+ ret = walk_call_func(ctx, conn, node, parent, arg,
-+ funcs->enter);
-+ }
-+
-+ talloc_free(tmpctx);
-+
-+ return ret < 0 ? ret : WALK_TREE_OK;
-+}
-+
- static struct {
- const char *str;
- int (*func)(const void *ctx, struct connection *conn,
-@@ -2206,18 +2335,6 @@ static int keys_equal_fn(void *key1, void *key2)
- return 0 == strcmp((char *)key1, (char *)key2);
- }
-
--
--static char *child_name(const char *s1, const char *s2)
--{
-- if (strcmp(s1, "/")) {
-- return talloc_asprintf(NULL, "%s/%s", s1, s2);
-- }
-- else {
-- return talloc_asprintf(NULL, "/%s", s2);
-- }
--}
--
--
- int remember_string(struct hashtable *hash, const char *str)
- {
- char *k = malloc(strlen(str) + 1);
-@@ -2277,7 +2394,7 @@ static int check_store_(const char *name, struct hashtable *reachable)
- while (i < node->childlen && !ret) {
- struct node *childnode;
- size_t childlen = strlen(node->children + i);
-- char * childname = child_name(node->name,
-+ char * childname = child_name(NULL, node->name,
- node->children + i);
-
- if (!childname) {
-diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
-index 1eb3708f82dd..f0fd8c352857 100644
---- a/tools/xenstore/xenstored_core.h
-+++ b/tools/xenstore/xenstored_core.h
-@@ -195,6 +195,7 @@ struct node {
-
- /* Children, each nul-terminated. */
- unsigned int childlen;
-+ unsigned int childoff; /* Used by walk_node_tree() internally. */
- char *children;
-
- /* Allocation information for node currently in store. */
-@@ -334,6 +335,45 @@ void read_state_buffered_data(const void *ctx, struct connection *conn,
- const struct xs_state_connection *sc);
- void read_state_node(const void *ctx, const void *state);
-
-+/*
-+ * Walk the node tree below root calling funcs->enter() and funcs->exit() for
-+ * each node. funcs->enter() is being called when entering a node, so before
-+ * any of the children of the node is processed. funcs->exit() is being
-+ * called when leaving the node, so after all children have been processed.
-+ * funcs->enoent() is being called when a node isn't existing.
-+ * funcs->*() return values:
-+ * < 0: tree walk is stopped, walk_node_tree() returns funcs->*() return value
-+ * in case WALK_TREE_ERROR_STOP is returned, errno should be set
-+ * WALK_TREE_OK: tree walk is continuing
-+ * WALK_TREE_SKIP_CHILDREN: tree walk won't descend below current node, but
-+ * walk continues
-+ * WALK_TREE_RM_CHILDENTRY: Remove the child entry from its parent and write
-+ * the modified parent node back to the data base, implies to not descend
-+ * below the current node, but to continue the walk
-+ * funcs->*() is allowed to modify the node it is called for in the data base.
-+ * In case funcs->enter() is deleting the node, it must not return WALK_TREE_OK
-+ * in order to avoid descending into no longer existing children.
-+ */
-+/* Return values for funcs->*() and walk_node_tree(). */
-+#define WALK_TREE_SUCCESS_STOP -100 /* Stop walk early, no error. */
-+#define WALK_TREE_ERROR_STOP -1 /* Stop walk due to error. */
-+#define WALK_TREE_OK 0 /* No error. */
-+/* Return value for funcs->*() only. */
-+#define WALK_TREE_SKIP_CHILDREN 1 /* Don't recurse below current node. */
-+#define WALK_TREE_RM_CHILDENTRY 2 /* Remove child entry from parent. */
-+
-+struct walk_funcs {
-+ int (*enter)(const void *ctx, struct connection *conn,
-+ struct node *node, void *arg);
-+ int (*exit)(const void *ctx, struct connection *conn,
-+ struct node *node, void *arg);
-+ int (*enoent)(const void *ctx, struct connection *conn,
-+ struct node *parent, char *name, void *arg);
-+};
-+
-+int walk_node_tree(const void *ctx, struct connection *conn, const char *root,
-+ struct walk_funcs *funcs, void *arg);
-+
- #endif /* _XENSTORED_CORE_H */
-
- /*
---
-2.37.4
-