File xsa326-13.patch of Package xen.26343

From fa2019ff2c0725c0d93f4be79a729515f70a1a40 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
Date: Tue, 13 Sep 2022 07:35:10 +0200
Subject: tools/xenstore: add memory accounting for watches

Add the memory accounting for registered watches.

When a socket connection is destroyed, the associated watches are
removed, too. In order to keep memory accounting correct the watches
must be removed explicitly via a call of conn_delete_all_watches() from
destroy_conn().

This is part of XSA-326 / CVE-2022-42315.

Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Julien Grall <jgrall@amazon.com>

diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
index 4f29439ad825..eca04e734a83 100644
--- a/tools/xenstore/xenstored_core.c
+++ b/tools/xenstore/xenstored_core.c
@@ -404,6 +404,7 @@ static int destroy_conn(void *_conn)
 	}
 
 	conn_free_buffered_data(conn);
+	conn_delete_all_watches(conn);
 	list_for_each_entry(req, &conn->ref_list, list)
 		req->on_ref_list = false;
 
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
index c50c0575f0f1..7118c30e8c32 100644
--- a/tools/xenstore/xenstored_watch.c
+++ b/tools/xenstore/xenstored_watch.c
@@ -224,7 +224,8 @@ int do_watch(struct connection *conn, struct buffered_data *in)
 		return ENOMEM;
 	watch->node = talloc_strdup(watch, vec[0]);
 	watch->token = talloc_strdup(watch, vec[1]);
-	if (!watch->node || !watch->token) {
+	if (!watch->node || !watch->token ||
+	    domain_memory_add_chk(conn->id, strlen(vec[0]) + strlen(vec[1]))) {
 		talloc_free(watch);
 		return ENOMEM;
 	}
@@ -265,6 +266,8 @@ int do_unwatch(struct connection *conn, struct buffered_data *in)
 	list_for_each_entry(watch, &conn->watches, list) {
 		if (streq(watch->node, node) && streq(watch->token, vec[1])) {
 			list_del(&watch->list);
+			domain_memory_add_nochk(conn->id, -strlen(watch->node) -
+							  strlen(watch->token));
 			talloc_free(watch);
 			domain_watch_dec(conn);
 			send_ack(conn, XS_UNWATCH);
@@ -280,6 +283,8 @@ void conn_delete_all_watches(struct connection *conn)
 
 	while ((watch = list_top(&conn->watches, struct watch, list))) {
 		list_del(&watch->list);
+		domain_memory_add_nochk(conn->id, -strlen(watch->node) -
+						  strlen(watch->token));
 		talloc_free(watch);
 		domain_watch_dec(conn);
 	}
openSUSE Build Service is sponsored by