Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
xen.27494
xsa414.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa414.patch of Package xen.27494
From: Julien Grall <jgrall@amazon.com> Subject: tools/xenstore: create_node: Don't defer work to undo any changes on failure XSA-115 extended destroy_node() to update the node accounting for the connection. The implementation is assuming the connection is the parent of the node, however all the nodes are allocated using a separate context (see process_message()). This will result to crash (or corrupt) xenstored as the pointer is wrongly used. In case of an error, any changes to the database or update to the accounting will now be reverted in create_node() by calling directly destroy_node(). This has the nice advantage to remove the loop to unset the destructors in case of success. Take the opportunity to free the nodes right now as they are not going to be reachable (the function returns NULL) and are just wasting resources. This is XSA-414 / CVE-2022-42309. Fixes: 0bfb2101f243 ("tools/xenstore: fix node accounting after failed node creation") Signed-off-by: Julien Grall <jgrall@amazon.com> Reviewed-by: Juergen Gross <jgross@suse.com> --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -975,9 +975,8 @@ nomem: return NULL; } -static int destroy_node(void *_node) +static int destroy_node(struct connection *conn, struct node *node) { - struct node *node = _node; TDB_DATA key; if (streq(node->name, "/")) @@ -988,7 +987,7 @@ static int destroy_node(void *_node) tdb_delete(tdb_ctx, key); - domain_entry_dec(talloc_parent(node), node); + domain_entry_dec(conn, node); return 0; } @@ -997,7 +996,8 @@ static struct node *create_node(struct c const char *name, void *data, unsigned int datalen) { - struct node *node, *i; + struct node *node, *i, *j; + int ret; node = construct_node(conn, ctx, name); if (!node) @@ -1019,23 +1019,40 @@ static struct node *create_node(struct c /* i->parent is set for each new node, so check quota. */ if (i->parent && domain_entry(conn) >= quota_nb_entry_per_domain) { - errno = ENOSPC; - return NULL; + ret = ENOSPC; + goto err; } - if (write_node(conn, i, false)) - return NULL; - /* Account for new node, set destructor for error case. */ - if (i->parent) { + ret = write_node(conn, i, false); + if (ret) + goto err; + + /* Account for new node */ + if (i->parent) domain_entry_inc(conn, i); - talloc_set_destructor(i, destroy_node); - } } - /* OK, now remove destructors so they stay around */ - for (i = node; i->parent; i = i->parent) - talloc_set_destructor(i, NULL); return node; + +err: + /* + * We failed to update TDB for some of the nodes. Undo any work that + * have already been done. + */ + for (j = node; j != i; j = j->parent) + destroy_node(conn, j); + + /* We don't need to keep the nodes around, so free them. */ + i = node; + while (i) { + j = i; + i = i->parent; + talloc_free(j); + } + + errno = ret; + + return NULL; } /* path, data... */
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