mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
tools/xenstore: simplify check_store()
check_store() is using a hash table for storing all node names it has
found via walking the tree. Additionally it using another hash table
for all children of a node to detect duplicate child names.
Simplify that by dropping the second hash table as the first one is
already holding all the needed information.
This is part of XSA-418 / CVE-2022-42321.
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>
(cherry picked from commit 70f719f52a)
This commit is contained in:
1 parent
d816b470e0
commit
ba1cff4b1b
1 file changed
+15
-28
@@ -2275,46 +2275,34 @@ static int check_store_(const char *name, struct hashtable *reachable)
|
||||
if (node) {
|
||||
size_t i = 0;
|
||||
|
||||
struct hashtable * children =
|
||||
create_hashtable(16, hash_from_key_fn, keys_equal_fn);
|
||||
|
||||
if (!remember_string(reachable, name)) {
|
||||
hashtable_destroy(children, 0);
|
||||
log("check_store: ENOMEM");
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
while (i < node->childlen && !ret) {
|
||||
struct node *childnode;
|
||||
struct node *childnode = NULL;
|
||||
size_t childlen = strlen(node->children + i);
|
||||
char * childname = child_name(NULL, node->name,
|
||||
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) {
|
||||
if (hashtable_search(children, childname)) {
|
||||
log("check_store: '%s' is duplicated!",
|
||||
childname);
|
||||
i = rm_child_entry(node, i, childlen);
|
||||
}
|
||||
else {
|
||||
if (!remember_string(children,
|
||||
childname)) {
|
||||
log("check_store: ENOMEM");
|
||||
talloc_free(childnode);
|
||||
talloc_free(childname);
|
||||
ret = ENOMEM;
|
||||
break;
|
||||
}
|
||||
ret = check_store_(childname,
|
||||
reachable);
|
||||
}
|
||||
ret = check_store_(childname, reachable);
|
||||
} else if (errno != ENOMEM) {
|
||||
log("check_store: No child '%s' found!\n",
|
||||
childname);
|
||||
@@ -2324,19 +2312,18 @@ static int check_store_(const char *name, struct hashtable *reachable)
|
||||
ret = ENOMEM;
|
||||
}
|
||||
|
||||
next:
|
||||
talloc_free(childnode);
|
||||
talloc_free(childname);
|
||||
i += childlen + 1;
|
||||
}
|
||||
|
||||
hashtable_destroy(children, 0 /* Don't free values (they are
|
||||
all (void *)1) */);
|
||||
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). */
|
||||
|
||||
|
||||
log("check_store: No child '%s' found: impossible!", name);
|
||||
} else {
|
||||
log("check_store: ENOMEM");
|
||||
|
||||