mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
tools/xenstored: make conn_delete_all_transactions() idempotent
conn_delete_all_transactions() should be callable in any context,
resetting ALL transaction related data.
This includes number of active transactions and the transaction
pointer in struct connection.
So reset conn->trans to NULL in conn_delete_all_transactions() and
do the cleanup for each transaction in destroy_transaction().
This avoids triggering the assert() in conn_delete_all_transactions()
in case e.g. ignore_connection() was called while an operation inside
a transaction was performed, or XS_RESET_WATCHES was called in a
transaction.
This is XSA-484 / CVE-2026-23557.
Reported-by: Andrii Sultanov <andriy.sultanov@vates.tech>
Fixes: 1f9d04fb02 ("xenstored: allow guest to shutdown all its watches/transactions")
Signed-off-by: Juergen Gross <jgross@suse.com>
This commit is contained in:
1 parent
af9e77f5ff
commit
e88031d1fe
1 file changed
+9
-11
@@ -434,17 +434,23 @@ static int finalize_transaction(struct connection *conn,
|
||||
static int destroy_transaction(void *_transaction)
|
||||
{
|
||||
struct transaction *trans = _transaction;
|
||||
struct connection *conn = trans->conn;
|
||||
struct accessed_node *i;
|
||||
|
||||
wrl_ntransactions--;
|
||||
trace_destroy(trans, "transaction");
|
||||
while ((i = list_top(&trans->accessed, struct accessed_node, list))) {
|
||||
if (i->ta_node)
|
||||
db_delete(trans->conn, i->trans_name, NULL);
|
||||
db_delete(conn, i->trans_name, NULL);
|
||||
list_del(&i->list);
|
||||
talloc_free(i);
|
||||
}
|
||||
|
||||
list_del(&trans->list);
|
||||
domain_transaction_dec(conn);
|
||||
if (list_empty(&conn->transaction_list))
|
||||
conn->ta_start_time = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -525,10 +531,6 @@ int do_transaction_end(const void *ctx, struct connection *conn,
|
||||
return ENOENT;
|
||||
|
||||
conn->transaction = NULL;
|
||||
list_del(&trans->list);
|
||||
domain_transaction_dec(conn);
|
||||
if (list_empty(&conn->transaction_list))
|
||||
conn->ta_start_time = 0;
|
||||
|
||||
chk_quota = trans->node_created && domain_is_unprivileged(conn);
|
||||
|
||||
@@ -574,14 +576,10 @@ void conn_delete_all_transactions(struct connection *conn)
|
||||
struct transaction *trans;
|
||||
|
||||
while ((trans = list_top(&conn->transaction_list,
|
||||
struct transaction, list))) {
|
||||
list_del(&trans->list);
|
||||
struct transaction, list)))
|
||||
talloc_free(trans);
|
||||
}
|
||||
|
||||
assert(conn->transaction == NULL);
|
||||
|
||||
conn->ta_start_time = 0;
|
||||
conn->transaction = NULL;
|
||||
}
|
||||
|
||||
int check_transactions(struct hashtable *hash)
|
||||
|
||||