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

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



commit 7985e875b9484723c81aed2b25aac9764fc60705
Author:     Juergen Gross <jgross@xxxxxxxx>
AuthorDate: Tue Apr 28 13:46:30 2026 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Apr 28 13:47:42 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/xenstore/xenstored_transaction.c | 20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/tools/xenstore/xenstored_transaction.c 
b/tools/xenstore/xenstored_transaction.c
index 8ebd16aed2..64e1f7fdd2 100644
--- a/tools/xenstore/xenstored_transaction.c
+++ b/tools/xenstore/xenstored_transaction.c
@@ -445,6 +445,7 @@ 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;
        TDB_DATA key;
 
@@ -453,12 +454,17 @@ static int destroy_transaction(void *_transaction)
        while ((i = list_top(&trans->accessed, struct accessed_node, list))) {
                if (i->ta_node) {
                        set_tdb_key(i->trans_name, &key);
-                       do_tdb_delete(trans->conn, &key, NULL);
+                       do_tdb_delete(conn, &key, NULL);
                }
                list_del(&i->list);
                talloc_free(i);
        }
 
+       list_del(&trans->list);
+       conn->transaction_started--;
+       if (!conn->transaction_started)
+               conn->ta_start_time = 0;
+
        return 0;
 }
 
@@ -561,10 +567,6 @@ int do_transaction_end(const void *ctx, struct connection 
*conn,
                return ENOENT;
 
        conn->transaction = NULL;
-       list_del(&trans->list);
-       conn->transaction_started--;
-       if (!conn->transaction_started)
-               conn->ta_start_time = 0;
 
        chk_quota = trans->node_created && domain_is_unprivileged(conn);
 
@@ -646,15 +648,11 @@ 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->transaction_started = 0;
-       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-4.17



 


Rackspace

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