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

[xen stable-4.21] tools/xenstored: make conn_delete_all_transactions() idempotent



commit 43e32ae4f92899b6ebd6730d944f51ba55dd88ae
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:42:30 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>
    (cherry picked from commit e88031d1fe5f5bbacc31b838c2a544de58c9bf45)
---
 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 167cd597fd..0825c48859 100644
--- a/tools/xenstored/transaction.c
+++ b/tools/xenstored/transaction.c
@@ -432,17 +432,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;
 }
 
@@ -523,10 +529,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);
 
@@ -572,14 +574,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#stable-4.21



 


Rackspace

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