+- oxenstored keeps quota related use counts across domain destruction + [XSA-483, CVE-2026-23556] +- Xenstored DoS via XS_RESET_WATCHES command [XSA-484, CVE-2026-23557] +- grant table v2 race in status page mapping [XSA-486, CVE-2026-23558] +- x86: Floating Point Divider State Sampling [XSA-488, CVE-2025-54505]
89 lines
2.7 KiB
Diff
89 lines
2.7 KiB
Diff
From 3d0d19ad17f29c64dde4a7baf392da4fd58f3654 Mon Sep 17 00:00:00 2001
|
|
From: Juergen Gross <jgross@suse.com>
|
|
Date: Mon, 16 Mar 2026 15:06:11 +0100
|
|
Subject: [PATCH] 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: 1f9d04fb021c ("xenstored: allow guest to shutdown all its watches/transactions")
|
|
Signed-off-by: Juergen Gross <jgross@suse.com>
|
|
---
|
|
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)
|
|
--
|
|
2.53.0
|
|
|