|
|
24e155b |
From cddf74031b3c8a108e8fd7db0bf56e9c2809d3e2 Mon Sep 17 00:00:00 2001
|
|
|
24e155b |
From: Juergen Gross <jgross@suse.com>
|
|
|
24e155b |
Date: Thu, 11 Jun 2020 16:12:45 +0200
|
|
|
24e155b |
Subject: [PATCH 09/10] tools/xenstore: allow special watches for privileged
|
|
|
24e155b |
callers only
|
|
|
24e155b |
|
|
|
24e155b |
The special watches "@introduceDomain" and "@releaseDomain" should be
|
|
|
24e155b |
allowed for privileged callers only, as they allow to gain information
|
|
|
24e155b |
about presence of other guests on the host. So send watch events for
|
|
|
24e155b |
those watches via privileged connections only.
|
|
|
24e155b |
|
|
|
24e155b |
In order to allow for disaggregated setups where e.g. driver domains
|
|
|
24e155b |
need to make use of those special watches add support for calling
|
|
|
24e155b |
"set permissions" for those special nodes, too.
|
|
|
24e155b |
|
|
|
24e155b |
This is part of XSA-115.
|
|
|
24e155b |
|
|
|
24e155b |
Signed-off-by: Juergen Gross <jgross@suse.com>
|
|
|
24e155b |
Reviewed-by: Julien Grall <jgrall@amazon.com>
|
|
|
24e155b |
Reviewed-by: Paul Durrant <paul@xen.org>
|
|
|
24e155b |
---
|
|
|
24e155b |
docs/misc/xenstore.txt | 5 +++
|
|
|
24e155b |
tools/xenstore/xenstored_core.c | 27 ++++++++------
|
|
|
24e155b |
tools/xenstore/xenstored_core.h | 2 ++
|
|
|
24e155b |
tools/xenstore/xenstored_domain.c | 60 +++++++++++++++++++++++++++++++
|
|
|
24e155b |
tools/xenstore/xenstored_domain.h | 5 +++
|
|
|
24e155b |
tools/xenstore/xenstored_watch.c | 4 +++
|
|
|
24e155b |
6 files changed, 93 insertions(+), 10 deletions(-)
|
|
|
24e155b |
|
|
|
24e155b |
diff --git a/docs/misc/xenstore.txt b/docs/misc/xenstore.txt
|
|
|
24e155b |
index 6f8569d5760f..32969eb3fecd 100644
|
|
|
24e155b |
--- a/docs/misc/xenstore.txt
|
|
|
24e155b |
+++ b/docs/misc/xenstore.txt
|
|
|
24e155b |
@@ -170,6 +170,9 @@ SET_PERMS <path>|<perm-as-string>|+?
|
|
|
24e155b |
n<domid> no access
|
|
|
24e155b |
See http://wiki.xen.org/wiki/XenBus section
|
|
|
24e155b |
`Permissions' for details of the permissions system.
|
|
|
24e155b |
+ It is possible to set permissions for the special watch paths
|
|
|
24e155b |
+ "@introduceDomain" and "@releaseDomain" to enable receiving those
|
|
|
24e155b |
+ watches in unprivileged domains.
|
|
|
24e155b |
|
|
|
24e155b |
---------- Watches ----------
|
|
|
24e155b |
|
|
|
24e155b |
@@ -194,6 +197,8 @@ WATCH <wpath>|<token>|?
|
|
|
24e155b |
@releaseDomain occurs on any domain crash or
|
|
|
24e155b |
shutdown, and also on RELEASE
|
|
|
24e155b |
and domain destruction
|
|
|
24e155b |
+ <wspecial> events are sent to privileged callers or explicitly
|
|
|
24e155b |
+ via SET_PERMS enabled domains only.
|
|
|
24e155b |
|
|
|
24e155b |
When a watch is first set up it is triggered once straight
|
|
|
24e155b |
away, with <path> equal to <wpath>. Watches may be triggered
|
|
|
24e155b |
diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_core.c
|
|
|
24e155b |
index fe9943113b9f..720bec269dd3 100644
|
|
|
24e155b |
--- a/tools/xenstore/xenstored_core.c
|
|
|
24e155b |
+++ b/tools/xenstore/xenstored_core.c
|
|
|
24e155b |
@@ -468,8 +468,8 @@ static int write_node(struct connection *conn, struct node *node,
|
|
|
24e155b |
return write_node_raw(conn, &key, node, no_quota_check);
|
|
|
24e155b |
}
|
|
|
24e155b |
|
|
|
24e155b |
-static enum xs_perm_type perm_for_conn(struct connection *conn,
|
|
|
24e155b |
- const struct node_perms *perms)
|
|
|
24e155b |
+enum xs_perm_type perm_for_conn(struct connection *conn,
|
|
|
24e155b |
+ const struct node_perms *perms)
|
|
|
24e155b |
{
|
|
|
24e155b |
unsigned int i;
|
|
|
24e155b |
enum xs_perm_type mask = XS_PERM_READ|XS_PERM_WRITE|XS_PERM_OWNER;
|
|
|
24e155b |
@@ -1245,22 +1245,29 @@ static int do_set_perms(struct connection *conn, struct buffered_data *in)
|
|
|
24e155b |
if (perms.num < 2)
|
|
|
24e155b |
return EINVAL;
|
|
|
24e155b |
|
|
|
24e155b |
- /* First arg is node name. */
|
|
|
24e155b |
- /* We must own node to do this (tools can do this too). */
|
|
|
24e155b |
- node = get_node_canonicalized(conn, in, in->buffer, &name,
|
|
|
24e155b |
- XS_PERM_WRITE | XS_PERM_OWNER);
|
|
|
24e155b |
- if (!node)
|
|
|
24e155b |
- return errno;
|
|
|
24e155b |
-
|
|
|
24e155b |
permstr = in->buffer + strlen(in->buffer) + 1;
|
|
|
24e155b |
perms.num--;
|
|
|
24e155b |
|
|
|
24e155b |
- perms.p = talloc_array(node, struct xs_permissions, perms.num);
|
|
|
24e155b |
+ perms.p = talloc_array(in, struct xs_permissions, perms.num);
|
|
|
24e155b |
if (!perms.p)
|
|
|
24e155b |
return ENOMEM;
|
|
|
24e155b |
if (!xs_strings_to_perms(perms.p, perms.num, permstr))
|
|
|
24e155b |
return errno;
|
|
|
24e155b |
|
|
|
24e155b |
+ /* First arg is node name. */
|
|
|
24e155b |
+ if (strstarts(in->buffer, "@")) {
|
|
|
24e155b |
+ if (set_perms_special(conn, in->buffer, &perms))
|
|
|
24e155b |
+ return errno;
|
|
|
24e155b |
+ send_ack(conn, XS_SET_PERMS);
|
|
|
24e155b |
+ return 0;
|
|
|
24e155b |
+ }
|
|
|
24e155b |
+
|
|
|
24e155b |
+ /* We must own node to do this (tools can do this too). */
|
|
|
24e155b |
+ node = get_node_canonicalized(conn, in, in->buffer, &name,
|
|
|
24e155b |
+ XS_PERM_WRITE | XS_PERM_OWNER);
|
|
|
24e155b |
+ if (!node)
|
|
|
24e155b |
+ return errno;
|
|
|
24e155b |
+
|
|
|
24e155b |
/* Unprivileged domains may not change the owner. */
|
|
|
24e155b |
if (domain_is_unprivileged(conn) &&
|
|
|
24e155b |
perms.p[0].id != node->perms.p[0].id)
|
|
|
24e155b |
diff --git a/tools/xenstore/xenstored_core.h b/tools/xenstore/xenstored_core.h
|
|
|
24e155b |
index 193d93142636..f3da6bbc943d 100644
|
|
|
24e155b |
--- a/tools/xenstore/xenstored_core.h
|
|
|
24e155b |
+++ b/tools/xenstore/xenstored_core.h
|
|
|
24e155b |
@@ -165,6 +165,8 @@ struct node *get_node(struct connection *conn,
|
|
|
24e155b |
struct connection *new_connection(connwritefn_t *write, connreadfn_t *read);
|
|
|
24e155b |
void check_store(void);
|
|
|
24e155b |
void corrupt(struct connection *conn, const char *fmt, ...);
|
|
|
24e155b |
+enum xs_perm_type perm_for_conn(struct connection *conn,
|
|
|
24e155b |
+ const struct node_perms *perms);
|
|
|
24e155b |
|
|
|
24e155b |
/* Is this a valid node name? */
|
|
|
24e155b |
bool is_valid_nodename(const char *node);
|
|
|
24e155b |
diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_domain.c
|
|
|
24e155b |
index dc51cdfa9aa7..7afabe0ae084 100644
|
|
|
24e155b |
--- a/tools/xenstore/xenstored_domain.c
|
|
|
24e155b |
+++ b/tools/xenstore/xenstored_domain.c
|
|
|
24e155b |
@@ -41,6 +41,9 @@ static evtchn_port_t virq_port;
|
|
|
24e155b |
|
|
|
24e155b |
xenevtchn_handle *xce_handle = NULL;
|
|
|
24e155b |
|
|
|
24e155b |
+static struct node_perms dom_release_perms;
|
|
|
24e155b |
+static struct node_perms dom_introduce_perms;
|
|
|
24e155b |
+
|
|
|
24e155b |
struct domain
|
|
|
24e155b |
{
|
|
|
24e155b |
struct list_head list;
|
|
|
24e155b |
@@ -589,6 +592,59 @@ void restore_existing_connections(void)
|
|
|
24e155b |
{
|
|
|
24e155b |
}
|
|
|
24e155b |
|
|
|
24e155b |
+static int set_dom_perms_default(struct node_perms *perms)
|
|
|
24e155b |
+{
|
|
|
24e155b |
+ perms->num = 1;
|
|
|
24e155b |
+ perms->p = talloc_array(NULL, struct xs_permissions, perms->num);
|
|
|
24e155b |
+ if (!perms->p)
|
|
|
24e155b |
+ return -1;
|
|
|
24e155b |
+ perms->p->id = 0;
|
|
|
24e155b |
+ perms->p->perms = XS_PERM_NONE;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ return 0;
|
|
|
24e155b |
+}
|
|
|
24e155b |
+
|
|
|
24e155b |
+static struct node_perms *get_perms_special(const char *name)
|
|
|
24e155b |
+{
|
|
|
24e155b |
+ if (!strcmp(name, "@releaseDomain"))
|
|
|
24e155b |
+ return &dom_release_perms;
|
|
|
24e155b |
+ if (!strcmp(name, "@introduceDomain"))
|
|
|
24e155b |
+ return &dom_introduce_perms;
|
|
|
24e155b |
+ return NULL;
|
|
|
24e155b |
+}
|
|
|
24e155b |
+
|
|
|
24e155b |
+int set_perms_special(struct connection *conn, const char *name,
|
|
|
24e155b |
+ struct node_perms *perms)
|
|
|
24e155b |
+{
|
|
|
24e155b |
+ struct node_perms *p;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ p = get_perms_special(name);
|
|
|
24e155b |
+ if (!p)
|
|
|
24e155b |
+ return EINVAL;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ if ((perm_for_conn(conn, p) & (XS_PERM_WRITE | XS_PERM_OWNER)) !=
|
|
|
24e155b |
+ (XS_PERM_WRITE | XS_PERM_OWNER))
|
|
|
24e155b |
+ return EACCES;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ p->num = perms->num;
|
|
|
24e155b |
+ talloc_free(p->p);
|
|
|
24e155b |
+ p->p = perms->p;
|
|
|
24e155b |
+ talloc_steal(NULL, perms->p);
|
|
|
24e155b |
+
|
|
|
24e155b |
+ return 0;
|
|
|
24e155b |
+}
|
|
|
24e155b |
+
|
|
|
24e155b |
+bool check_perms_special(const char *name, struct connection *conn)
|
|
|
24e155b |
+{
|
|
|
24e155b |
+ struct node_perms *p;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ p = get_perms_special(name);
|
|
|
24e155b |
+ if (!p)
|
|
|
24e155b |
+ return false;
|
|
|
24e155b |
+
|
|
|
24e155b |
+ return perm_for_conn(conn, p) & XS_PERM_READ;
|
|
|
24e155b |
+}
|
|
|
24e155b |
+
|
|
|
24e155b |
static int dom0_init(void)
|
|
|
24e155b |
{
|
|
|
24e155b |
evtchn_port_t port;
|
|
|
24e155b |
@@ -610,6 +666,10 @@ static int dom0_init(void)
|
|
|
24e155b |
|
|
|
24e155b |
xenevtchn_notify(xce_handle, dom0->port);
|
|
|
24e155b |
|
|
|
24e155b |
+ if (set_dom_perms_default(&dom_release_perms) ||
|
|
|
24e155b |
+ set_dom_perms_default(&dom_introduce_perms))
|
|
|
24e155b |
+ return -1;
|
|
|
24e155b |
+
|
|
|
24e155b |
return 0;
|
|
|
24e155b |
}
|
|
|
24e155b |
|
|
|
24e155b |
diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_domain.h
|
|
|
24e155b |
index 56ae01597475..259183962a9c 100644
|
|
|
24e155b |
--- a/tools/xenstore/xenstored_domain.h
|
|
|
24e155b |
+++ b/tools/xenstore/xenstored_domain.h
|
|
|
24e155b |
@@ -65,6 +65,11 @@ void domain_watch_inc(struct connection *conn);
|
|
|
24e155b |
void domain_watch_dec(struct connection *conn);
|
|
|
24e155b |
int domain_watch(struct connection *conn);
|
|
|
24e155b |
|
|
|
24e155b |
+/* Special node permission handling. */
|
|
|
24e155b |
+int set_perms_special(struct connection *conn, const char *name,
|
|
|
24e155b |
+ struct node_perms *perms);
|
|
|
24e155b |
+bool check_perms_special(const char *name, struct connection *conn);
|
|
|
24e155b |
+
|
|
|
24e155b |
/* Write rate limiting */
|
|
|
24e155b |
|
|
|
24e155b |
#define WRL_FACTOR 1000 /* for fixed-point arithmetic */
|
|
|
24e155b |
diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_watch.c
|
|
|
24e155b |
index 3836675459fa..f4e289362eb6 100644
|
|
|
24e155b |
--- a/tools/xenstore/xenstored_watch.c
|
|
|
24e155b |
+++ b/tools/xenstore/xenstored_watch.c
|
|
|
24e155b |
@@ -133,6 +133,10 @@ void fire_watches(struct connection *conn, const void *ctx, const char *name,
|
|
|
24e155b |
|
|
|
24e155b |
/* Create an event for each watch. */
|
|
|
24e155b |
list_for_each_entry(i, &connections, list) {
|
|
|
24e155b |
+ /* introduce/release domain watches */
|
|
|
24e155b |
+ if (check_special_event(name) && !check_perms_special(name, i))
|
|
|
24e155b |
+ continue;
|
|
|
24e155b |
+
|
|
|
24e155b |
list_for_each_entry(watch, &i->watches, list) {
|
|
|
24e155b |
if (exact) {
|
|
|
24e155b |
if (streq(name, watch->node))
|
|
|
24e155b |
--
|
|
|
24e155b |
2.17.1
|
|
|
24e155b |
|