File xsa418-04.patch of Package xen.32200
From d58d069b0af5e64b667609723ba24ad5242fc920 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: 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>
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -2275,46 +2275,34 @@ static int check_store_(const char *name
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
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");