From 0cff16f0a997f1b0871b621a1d6050652530e5d9 Mon Sep 17 00:00:00 2001
From: Juergen Gross <jgross@suse.com>
Date: Thu, 12 Feb 2026 08:29:38 +0100
Subject: [PATCH] tools/xenstored: fix canonicalize() error testing
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The setting of errno in canonicalize() is rather fragile and seems to
be even wrong in one corner case: when the invalid path "/local/domain/"
is passed, sscanf() will set errno to 0, resulting in canonicalize() to
return NULL with errno being 0. This can result in triggering the
assert(conn->in == NULL) in consider_message().

Don't assume the initial setting of errno to "EINVAL" will stay valid
in all cases and set it to EINVAL only when returning NULL due to an
invalid path.

This is XSA-481/CVE-2026-23555

Reported-by: Marek Marczykowski-Górecki <marmarek@invisiblethingslab.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: Julien Grall <julien@xen.org>
---
 tools/xenstored/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tools/xenstored/core.c b/tools/xenstored/core.c
index 64c478a801..2e826f99eb 100644
--- a/tools/xenstored/core.c
+++ b/tools/xenstored/core.c
@@ -1240,11 +1240,10 @@ const char *canonicalize(struct connection *conn, const void *ctx,
 	 * - illegal character in node
 	 * - starts with '@' but no special node allowed
 	 */
-	errno = EINVAL;
 	if (!node ||
 	    !valid_chars(node) ||
 	    (node[0] == '@' && !allow_special))
-		return NULL;
+		goto inval;
 
 	if (node[0] != '/' && node[0] != '@') {
 		name = talloc_asprintf(ctx, "%s/%s", get_implicit_path(conn),
@@ -1272,6 +1271,8 @@ const char *canonicalize(struct connection *conn, const void *ctx,
 	if (name != node)
 		talloc_free(name);
 
+ inval:
+	errno = EINVAL;
 	return NULL;
 }
 
-- 
2.53.0

