Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP7:GA
xen.30827
xsa418-05.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa418-05.patch of Package xen.30827
From ac24da3fde16215b4ba5f0cc8d9686881e97bb42 Mon Sep 17 00:00:00 2001 From: Juergen Gross <jgross@suse.com> Date: Tue, 13 Sep 2022 07:35:12 +0200 Subject: tools/xenstore: use treewalk for check_store() Instead of doing an open tree walk using call recursion, use walk_node_tree() when checking the store for inconsistencies. This will reduce code size and avoid many nesting levels of function calls which could potentially exhaust the stack. This is part of XSA-418 / CVE-2022-42321. Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Julien Grall <jgrall@amazon.com> --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -2242,18 +2242,6 @@ int remember_string(struct hashtable *ha return hashtable_insert(hash, k, (void *)1); } -static int rm_child_entry(struct node *node, size_t off, size_t len) -{ - if (!recovery) - return off; - - if (remove_child_entry(NULL, node, off)) - log("check_store: child entry could not be removed from '%s'", - node->name); - - return off - len - 1; -} - /** * A node has a children field that names the children of the node, separated * by NULs. We check whether there are entries in there that are duplicated @@ -2267,70 +2255,29 @@ static int rm_child_entry(struct node *n * As we go, we record each node in the given reachable hashtable. These * entries will be used later in clean_store. */ -static int check_store_(const char *name, struct hashtable *reachable) +static int check_store_step(const void *ctx, struct connection *conn, + struct node *node, void *arg) { - struct node *node = read_node(NULL, name, name); - int ret = 0; - - if (node) { - size_t i = 0; + struct hashtable *reachable = arg; - if (!remember_string(reachable, name)) { - log("check_store: ENOMEM"); - return ENOMEM; - } + if (hashtable_search(reachable, (void *)node->name)) { + log("check_store: '%s' is duplicated!", node->name); + return recovery ? WALK_TREE_RM_CHILDENTRY + : WALK_TREE_SKIP_CHILDREN; + } - while (i < node->childlen && !ret) { - struct node *childnode = NULL; - size_t childlen = strlen(node->children + i); - char *childname = child_name(NULL, node->name, - node->children + i); - - if (!childname) { - log("check_store: ENOMEM"); - ret = ENOMEM; - break; - } - - if (hashtable_search(reachable, childname)) { - log("check_store: '%s' is duplicated!", - childname); - i = rm_child_entry(node, i, childlen); - goto next; - } - - childnode = read_node(NULL, childname, childname); - - if (childnode) { - ret = check_store_(childname, reachable); - } else if (errno != ENOMEM) { - log("check_store: No child '%s' found!\n", - childname); - i = rm_child_entry(node, i, childlen); - } else { - log("check_store: ENOMEM"); - ret = ENOMEM; - } - - next: - talloc_free(childnode); - talloc_free(childname); - i += childlen + 1; - } + if (!remember_string(reachable, node->name)) + return WALK_TREE_ERROR_STOP; - talloc_free(node); - } else if (errno != ENOMEM) { - /* Impossible, because no database should ever be without the - root, and otherwise, we've just checked in our caller - (which made a recursive call to get here). */ + return WALK_TREE_OK; +} - log("check_store: No child '%s' found: impossible!", name); - } else { - log("check_store: ENOMEM"); - ret = ENOMEM; - } +static int check_store_enoent(const void *ctx, struct connection *conn, + struct node *parent, char *name, void *arg) +{ + log("check_store: node '%s' not found", name); - return ret; + return recovery ? WALK_TREE_RM_CHILDENTRY : WALK_TREE_OK; } @@ -2379,24 +2326,28 @@ static void clean_store(struct hashtable void check_store(void) { - char * root = talloc_strdup(NULL, "/"); - struct hashtable * reachable = - create_hashtable(16, hash_from_key_fn, keys_equal_fn); - + struct hashtable *reachable; + struct walk_funcs walkfuncs = { + .enter = check_store_step, + .enoent = check_store_enoent, + }; + + reachable = create_hashtable(16, hash_from_key_fn, keys_equal_fn); if (!reachable) { log("check_store: ENOMEM"); return; } log("Checking store ..."); - if (!check_store_(root, reachable) && - !check_transactions(reachable)) + if (walk_node_tree(NULL, NULL, "/", &walkfuncs, reachable)) { + if (errno == ENOMEM) + log("check_store: ENOMEM"); + } else if (!check_transactions(reachable)) clean_store(reachable); log("Checking store complete."); hashtable_destroy(reachable, 0 /* Don't free values (they are all (void *)1) */); - talloc_free(root); }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor