[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] tools/xenstored: make conn_delete_all_transactions() idempotent



commit e88031d1fe5f5bbacc31b838c2a544de58c9bf45
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Mon Mar 16 15:06:11 2026 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Apr 28 13:41:32 2026 +0100

    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@xxxxxxxxxx>
    Fixes: 1f9d04fb021c ("xenstored: allow guest to shutdown all its 
watches/transactions")
    Signed-off-by: Juergen Gross <jgross@xxxxxxxx>
---
 tools/xenstored/transaction.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/tools/xenstored/transaction.c b/tools/xenstored/transaction.c
index ec5b122a3f..c6519164be 100644
--- a/tools/xenstored/transaction.c
+++ b/tools/xenstored/transaction.c
@@ -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)
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.