|
|
97374c0 |
From 67d5ecd609b8f12346eadb40e547cd7e01d825dc Mon Sep 17 00:00:00 2001
|
|
|
97374c0 |
From: Juergen Gross <jgross@suse.com>
|
|
|
97374c0 |
Date: Tue, 13 Sep 2022 07:35:10 +0200
|
|
|
97374c0 |
Subject: tools/xenstore: fix checking node permissions
|
|
|
97374c0 |
|
|
|
97374c0 |
Today chk_domain_generation() is being used to check whether a node
|
|
|
97374c0 |
permission entry is still valid or whether it is referring to a domain
|
|
|
97374c0 |
no longer existing. This is done by comparing the node's and the
|
|
|
97374c0 |
domain's generation count.
|
|
|
97374c0 |
|
|
|
97374c0 |
In case no struct domain is existing for a checked domain, but the
|
|
|
97374c0 |
domain itself is valid, chk_domain_generation() assumes it is being
|
|
|
97374c0 |
called due to the first node created for a new domain and it will
|
|
|
97374c0 |
return success.
|
|
|
97374c0 |
|
|
|
97374c0 |
This might be wrong in case the checked permission is related to an
|
|
|
97374c0 |
old domain, which has just been replaced with a new domain using the
|
|
|
97374c0 |
same domid.
|
|
|
97374c0 |
|
|
|
97374c0 |
Fix that by letting chk_domain_generation() fail in case a struct
|
|
|
97374c0 |
domain isn't found. In order to cover the case of the first node for
|
|
|
97374c0 |
a new domain try to allocate the needed struct domain explicitly when
|
|
|
97374c0 |
processing the related SET_PERMS command. In case a referenced domain
|
|
|
97374c0 |
isn't existing, flag the related permission to be ignored right away.
|
|
|
97374c0 |
|
|
|
97374c0 |
This is XSA-417 / CVE-2022-42320.
|
|
|
97374c0 |
|
|
|
97374c0 |
Reported-by: Juergen Gross <jgross@suse.com>
|
|
|
97374c0 |
Signed-off-by: Juergen Gross <jgross@suse.com>
|
|
|
97374c0 |
Reviewed-by: Julien Grall <jgrall@amazon.com>
|
|
|
97374c0 |
|
|
|
97374c0 |
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
|
|
|
97374c0 |
index 66bbeaf6bfb0..a0c176fa203e 100644
|
|
|
97374c0 |
--- a/tools/xenstore/xenstored_core.c
|
|
|
97374c0 |
+++ b/tools/xenstore/xenstored_core.c
|
|
|
97374c0 |
@@ -1753,6 +1753,11 @@ static int do_set_perms(const void *ctx, struct connection *conn,
|
|
|
97374c0 |
if (!xs_strings_to_perms(perms.p, perms.num, permstr))
|
|
|
97374c0 |
return errno;
|
|
|
97374c0 |
|
|
|
97374c0 |
+ if (domain_alloc_permrefs(&perms) < 0)
|
|
|
97374c0 |
+ return ENOMEM;
|
|
|
97374c0 |
+ if (perms.p[0].perms & XS_PERM_IGNORE)
|
|
|
97374c0 |
+ return ENOENT;
|
|
|
97374c0 |
+
|
|
|
97374c0 |
/* First arg is node name. */
|
|
|
97374c0 |
if (strstarts(in->buffer, "@")) {
|
|
|
97374c0 |
if (set_perms_special(conn, in->buffer, &perms))
|
|
|
97374c0 |
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
|
|
|
97374c0 |
index b9ff4ded8360..98b401fdec30 100644
|
|
|
97374c0 |
--- a/tools/xenstore/xenstored_domain.c
|
|
|
97374c0 |
+++ b/tools/xenstore/xenstored_domain.c
|
|
|
97374c0 |
@@ -907,7 +907,6 @@ int domain_entry_inc(struct connection *conn, struct node *node)
|
|
|
97374c0 |
* count (used for testing whether a node permission is older than a domain).
|
|
|
97374c0 |
*
|
|
|
97374c0 |
* Return values:
|
|
|
97374c0 |
- * -1: error
|
|
|
97374c0 |
* 0: domain has higher generation count (it is younger than a node with the
|
|
|
97374c0 |
* given count), or domain isn't existing any longer
|
|
|
97374c0 |
* 1: domain is older than the node
|
|
|
97374c0 |
@@ -915,20 +914,38 @@ int domain_entry_inc(struct connection *conn, struct node *node)
|
|
|
97374c0 |
static int chk_domain_generation(unsigned int domid, uint64_t gen)
|
|
|
97374c0 |
{
|
|
|
97374c0 |
struct domain *d;
|
|
|
97374c0 |
- xc_dominfo_t dominfo;
|
|
|
97374c0 |
|
|
|
97374c0 |
if (!xc_handle && domid == 0)
|
|
|
97374c0 |
return 1;
|
|
|
97374c0 |
|
|
|
97374c0 |
d = find_domain_struct(domid);
|
|
|
97374c0 |
- if (d)
|
|
|
97374c0 |
- return (d->generation <= gen) ? 1 : 0;
|
|
|
97374c0 |
|
|
|
97374c0 |
- if (!get_domain_info(domid, &dominfo))
|
|
|
97374c0 |
- return 0;
|
|
|
97374c0 |
+ return (d && d->generation <= gen) ? 1 : 0;
|
|
|
97374c0 |
+}
|
|
|
97374c0 |
|
|
|
97374c0 |
- d = alloc_domain(NULL, domid);
|
|
|
97374c0 |
- return d ? 1 : -1;
|
|
|
97374c0 |
+/*
|
|
|
97374c0 |
+ * Allocate all missing struct domain referenced by a permission set.
|
|
|
97374c0 |
+ * Any permission entries for not existing domains will be marked to be
|
|
|
97374c0 |
+ * ignored.
|
|
|
97374c0 |
+ */
|
|
|
97374c0 |
+int domain_alloc_permrefs(struct node_perms *perms)
|
|
|
97374c0 |
+{
|
|
|
97374c0 |
+ unsigned int i, domid;
|
|
|
97374c0 |
+ struct domain *d;
|
|
|
97374c0 |
+ xc_dominfo_t dominfo;
|
|
|
97374c0 |
+
|
|
|
97374c0 |
+ for (i = 0; i < perms->num; i++) {
|
|
|
97374c0 |
+ domid = perms->p[i].id;
|
|
|
97374c0 |
+ d = find_domain_struct(domid);
|
|
|
97374c0 |
+ if (!d) {
|
|
|
97374c0 |
+ if (!get_domain_info(domid, &dominfo))
|
|
|
97374c0 |
+ perms->p[i].perms |= XS_PERM_IGNORE;
|
|
|
97374c0 |
+ else if (!alloc_domain(NULL, domid))
|
|
|
97374c0 |
+ return ENOMEM;
|
|
|
97374c0 |
+ }
|
|
|
97374c0 |
+ }
|
|
|
97374c0 |
+
|
|
|
97374c0 |
+ return 0;
|
|
|
97374c0 |
}
|
|
|
97374c0 |
|
|
|
97374c0 |
/*
|
|
|
97374c0 |
@@ -941,8 +958,6 @@ int domain_adjust_node_perms(struct connection *conn, struct node *node)
|
|
|
97374c0 |
int ret;
|
|
|
97374c0 |
|
|
|
97374c0 |
ret = chk_domain_generation(node->perms.p[0].id, node->generation);
|
|
|
97374c0 |
- if (ret < 0)
|
|
|
97374c0 |
- return errno;
|
|
|
97374c0 |
|
|
|
97374c0 |
/* If the owner doesn't exist any longer give it to priv domain. */
|
|
|
97374c0 |
if (!ret) {
|
|
|
97374c0 |
@@ -959,8 +974,6 @@ int domain_adjust_node_perms(struct connection *conn, struct node *node)
|
|
|
97374c0 |
continue;
|
|
|
97374c0 |
ret = chk_domain_generation(node->perms.p[i].id,
|
|
|
97374c0 |
node->generation);
|
|
|
97374c0 |
- if (ret < 0)
|
|
|
97374c0 |
- return errno;
|
|
|
97374c0 |
if (!ret)
|
|
|
97374c0 |
node->perms.p[i].perms |= XS_PERM_IGNORE;
|
|
|
97374c0 |
}
|
|
|
97374c0 |
diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
|
|
|
97374c0 |
index 209442190911..7fe0a21d9e45 100644
|
|
|
97374c0 |
--- a/tools/xenstore/xenstored_domain.h
|
|
|
97374c0 |
+++ b/tools/xenstore/xenstored_domain.h
|
|
|
97374c0 |
@@ -63,6 +63,7 @@ bool domain_is_unprivileged(struct connection *conn);
|
|
|
97374c0 |
|
|
|
97374c0 |
/* Remove node permissions for no longer existing domains. */
|
|
|
97374c0 |
int domain_adjust_node_perms(struct connection *conn, struct node *node);
|
|
|
97374c0 |
+int domain_alloc_permrefs(struct node_perms *perms);
|
|
|
97374c0 |
|
|
|
97374c0 |
/* Quota manipulation */
|
|
|
97374c0 |
int domain_entry_inc(struct connection *conn, struct node *);
|