Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
xen.26659
xsa415.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File xsa415.patch of Package xen.26659
From: Julien Grall <jgrall@amazon.com> Subject: tools/xenstore: Fail a transaction if it is not possible to create a node Commit f2bebf72c4d5 "xenstore: rework of transaction handling" moved out from copying the entire database everytime a new transaction is opened to track the list of nodes changed. The content of all the nodes accessed during a transaction will be temporarily stored in TDB using a different key. The function create_node() may write/update multiple nodes if the child doesn't exist. In case of a failure, the function will revert any changes (this include any update to TDB). Unfortunately, the function which reverts the changes (i.e. destroy_node()) will not use the correct key to delete any update or even request the transaction to fail. This means that if a client decide to go ahead with committing the transaction, orphan nodes will be created because they were not linked to an existing node (create_node() will write the nodes backwards). Once some nodes have been partially updated in a transaction, it is not easily possible to undo any changes. So rather than continuing and hit weird issue while committing, it is much saner to fail the transaction. This will have an impact on any client that decides to commit even if it can't write a node. Although, it is not clear why a normal client would want to do that... Lastly, update destroy_node() to use the correct key for deleting the node. Rather than recreating it (this will allocate memory and therefore fail), stash the key in the structure node. This is XSA-415 / CVE-2022-42310. Signed-off-by: Julien Grall <jgrall@amazon.com> Reviewed-by: Juergen Gross <jgross@suse.com> diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index 6afe8cb59d7e..8e91b554984d 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -468,15 +468,17 @@ int write_node_raw(struct connection *conn, TDB_DATA *key, struct node *node, return 0; } +/* + * Write the node. If the node is written, caller can find the key used in + * node->key. This can later be used if the change needs to be reverted. + */ static int write_node(struct connection *conn, struct node *node, bool no_quota_check) { - TDB_DATA key; - - if (access_node(conn, node, NODE_ACCESS_WRITE, &key)) + if (access_node(conn, node, NODE_ACCESS_WRITE, &node->key)) return errno; - return write_node_raw(conn, &key, node, no_quota_check); + return write_node_raw(conn, &node->key, node, no_quota_check); } enum xs_perm_type perm_for_conn(struct connection *conn, @@ -979,18 +981,21 @@ static struct node *construct_node(struct connection *conn, const void *ctx, static int destroy_node(struct connection *conn, struct node *node) { - TDB_DATA key; - if (streq(node->name, "/")) corrupt(NULL, "Destroying root node!"); - key.dptr = (void *)node->name; - key.dsize = strlen(node->name); - - tdb_delete(tdb_ctx, key); + tdb_delete(tdb_ctx, node->key); domain_entry_dec(conn, node); + /* + * It is not possible to easily revert the changes in a transaction. + * So if the failure happens in a transaction, mark it as fail to + * prevent any commit. + */ + if ( conn->transaction ) + fail_transaction(conn->transaction); + return 0; } diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h index 196a6fd2b0be..9369c4cbfd26 100644 --- a/tools/xenstore/xenstored_core.h +++ b/tools/xenstore/xenstored_core.h @@ -119,6 +119,8 @@ struct node_perms { struct node { const char *name; + /* Key used to update TDB */ + TDB_DATA key; /* Parent (optional) */ struct node *parent; diff --git a/tools/xenstore/xenstored_transaction.c b/tools/xenstore/xenstored_transaction.c index 2881f3b2e44d..4ffa18311120 100644 --- a/tools/xenstore/xenstored_transaction.c +++ b/tools/xenstore/xenstored_transaction.c @@ -582,6 +582,11 @@ void transaction_entry_dec(struct transaction *trans, unsigned int domid) list_add_tail(&d->list, &trans->changed_domains); } +void fail_transaction(struct transaction *trans) +{ + trans->fail = true; +} + void conn_delete_all_transactions(struct connection *conn) { struct transaction *trans; diff --git a/tools/xenstore/xenstored_transaction.h b/tools/xenstore/xenstored_transaction.h index 43a162bea3f3..14062730e3c9 100644 --- a/tools/xenstore/xenstored_transaction.h +++ b/tools/xenstore/xenstored_transaction.h @@ -46,6 +46,9 @@ int access_node(struct connection *conn, struct node *node, int transaction_prepend(struct connection *conn, const char *name, TDB_DATA *key); +/* Mark the transaction as failed. This will prevent it to be committed. */ +void fail_transaction(struct transaction *trans); + void conn_delete_all_transactions(struct connection *conn); int check_transactions(struct hashtable *hash);
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