[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen staging-4.13] tools/xenstore: fix checking node permissions
commit e6655e8f25e4ebf3d3cabac2430c8d5ba33a15a5 Author: Juergen Gross <jgross@xxxxxxxx> AuthorDate: Tue Sep 13 07:35:10 2022 +0200 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Tue Nov 1 15:25:15 2022 +0000 tools/xenstore: fix checking node permissions Today chk_domain_generation() is being used to check whether a node permission entry is still valid or whether it is referring to a domain no longer existing. This is done by comparing the node's and the domain's generation count. In case no struct domain is existing for a checked domain, but the domain itself is valid, chk_domain_generation() assumes it is being called due to the first node created for a new domain and it will return success. This might be wrong in case the checked permission is related to an old domain, which has just been replaced with a new domain using the same domid. Fix that by letting chk_domain_generation() fail in case a struct domain isn't found. In order to cover the case of the first node for a new domain try to allocate the needed struct domain explicitly when processing the related SET_PERMS command. In case a referenced domain isn't existing, flag the related permission to be ignored right away. This is XSA-417 / CVE-2022-42320. Signed-off-by: Juergen Gross <jgross@xxxxxxxx> Reviewed-by: Julien Grall <jgrall@xxxxxxxxxx> (cherry picked from commit ab128218225d3542596ca3a02aee80d55494bef8) --- tools/xenstore/xenstored_core.c | 5 +++++ tools/xenstore/xenstored_domain.c | 37 +++++++++++++++++++++++++------------ tools/xenstore/xenstored_domain.h | 1 + 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c index d6bbb532fb..25064427be 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -1640,6 +1640,11 @@ static int do_set_perms(const void *ctx, struct connection *conn, if (!xs_strings_to_perms(perms.p, perms.num, permstr)) return errno; + if (domain_alloc_permrefs(&perms) < 0) + return ENOMEM; + if (perms.p[0].perms & XS_PERM_IGNORE) + return ENOENT; + /* First arg is node name. */ if (strstarts(in->buffer, "@")) { if (set_perms_special(conn, in->buffer, &perms)) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c index 3e2f49985a..43fc2c4879 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -866,7 +866,6 @@ int domain_entry_inc(struct connection *conn, struct node *node) * count (used for testing whether a node permission is older than a domain). * * Return values: - * -1: error * 0: domain has higher generation count (it is younger than a node with the * given count), or domain isn't existing any longer * 1: domain is older than the node @@ -874,20 +873,38 @@ int domain_entry_inc(struct connection *conn, struct node *node) static int chk_domain_generation(unsigned int domid, uint64_t gen) { struct domain *d; - xc_dominfo_t dominfo; if (!xc_handle && domid == 0) return 1; d = find_domain_struct(domid); - if (d) - return (d->generation <= gen) ? 1 : 0; - if (!get_domain_info(domid, &dominfo)) - return 0; + return (d && d->generation <= gen) ? 1 : 0; +} - d = alloc_domain(NULL, domid); - return d ? 1 : -1; +/* + * Allocate all missing struct domain referenced by a permission set. + * Any permission entries for not existing domains will be marked to be + * ignored. + */ +int domain_alloc_permrefs(struct node_perms *perms) +{ + unsigned int i, domid; + struct domain *d; + xc_dominfo_t dominfo; + + for (i = 0; i < perms->num; i++) { + domid = perms->p[i].id; + d = find_domain_struct(domid); + if (!d) { + if (!get_domain_info(domid, &dominfo)) + perms->p[i].perms |= XS_PERM_IGNORE; + else if (!alloc_domain(NULL, domid)) + return ENOMEM; + } + } + + return 0; } /* @@ -900,8 +917,6 @@ int domain_adjust_node_perms(struct connection *conn, struct node *node) int ret; ret = chk_domain_generation(node->perms.p[0].id, node->generation); - if (ret < 0) - return errno; /* If the owner doesn't exist any longer give it to priv domain. */ if (!ret) { @@ -918,8 +933,6 @@ int domain_adjust_node_perms(struct connection *conn, struct node *node) continue; ret = chk_domain_generation(node->perms.p[i].id, node->generation); - if (ret < 0) - return errno; if (!ret) node->perms.p[i].perms |= XS_PERM_IGNORE; } diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h index 732eb8fa75..bab405209e 100644 --- a/tools/xenstore/xenstored_domain.h +++ b/tools/xenstore/xenstored_domain.h @@ -65,6 +65,7 @@ bool domain_is_unprivileged(struct connection *conn); /* Remove node permissions for no longer existing domains. */ int domain_adjust_node_perms(struct connection *conn, struct node *node); +int domain_alloc_permrefs(struct node_perms *perms); /* Quota manipulation */ int domain_entry_inc(struct connection *conn, struct node *); -- generated by git-patchbot for /home/xen/git/xen.git#staging-4.13
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |