From nobody Thu Nov 28 13:57:13 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=suse.com ARC-Seal: i=1; a=rsa-sha256; t=1670947565; cv=none; d=zohomail.com; s=zohoarc; b=Kh8tyRTMweVx+zhiZp5a/QlEZDLom3gnd6xEqC8vvBzju/+awv5hyAruBOUBhhGEs+gwEtlekE4+wqEMwQrusau20Iv785vVxV2OqRWUgI9N76V+s17LGyuv9TREp97YwaTGKptm5zfZW/gDQyG94LlBbjQTHLJG25nACT7mmS4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1670947565; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=4icxtWJv46RMUBYYAQr+H73PUdXTpWFKC53mCeCpDfA=; b=VbGqVorRF4WZ3gEVBkaTNr09YOHUeT8hduycgSEckuOhrXYv0dgC5c1LhurRgtJJpOrFSQXZqicNhIlwf2MpSY8Wn0+sRydjid912HNEsjNbv6s+ipkmjo7wuZaBHJ0WrGZoWrRE8RRW6/DG8ryLCn9Lh31oeWEnaTy7y9TE8GU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1670947565977654.5879495753746; Tue, 13 Dec 2022 08:06:05 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.460808.718885 (Exim 4.92) (envelope-from ) id 1p57ma-0001we-42; Tue, 13 Dec 2022 16:05:28 +0000 Received: by outflank-mailman (output) from mailman id 460808.718885; Tue, 13 Dec 2022 16:05:28 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1p57mZ-0001vV-RD; Tue, 13 Dec 2022 16:05:27 +0000 Received: by outflank-mailman (input) for mailman id 460808; Tue, 13 Dec 2022 16:05:26 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1p57ii-0001ta-Km for xen-devel@lists.xenproject.org; Tue, 13 Dec 2022 16:01:28 +0000 Received: from smtp-out1.suse.de (smtp-out1.suse.de [195.135.220.28]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 66557bf7-7aff-11ed-8fd2-01056ac49cbb; Tue, 13 Dec 2022 17:01:27 +0100 (CET) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out1.suse.de (Postfix) with ESMTPS id ED7DE22087; Tue, 13 Dec 2022 16:01:26 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id BD70D138EE; Tue, 13 Dec 2022 16:01:26 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id 2Nz+LNahmGPBKQAAMHmgww (envelope-from ); Tue, 13 Dec 2022 16:01:26 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 66557bf7-7aff-11ed-8fd2-01056ac49cbb DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1670947286; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=4icxtWJv46RMUBYYAQr+H73PUdXTpWFKC53mCeCpDfA=; b=JvzyOxirX/TgVXvWjLGFTH6uFi+zHVsunKLrREYWc88Cp/kx8jbL6dFJbrMWqQ7AO92/uQ PYiF3nPw8gRcs0myj35udMyPokv0tTCM1vsDnJvKmNjY4cYXpSzjejYKd9dzq4yj6TRcVv 8mKVX6GVOih2SqMpN9hpklVtaRQ4COs= From: Juergen Gross To: xen-devel@lists.xenproject.org Cc: Juergen Gross , Wei Liu , Julien Grall , Anthony PERARD Subject: [PATCH v2 07/19] tools/xenstore: introduce dummy nodes for special watch paths Date: Tue, 13 Dec 2022 17:00:33 +0100 Message-Id: <20221213160045.28170-8-jgross@suse.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20221213160045.28170-1-jgross@suse.com> References: <20221213160045.28170-1-jgross@suse.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1670947567587100007 Content-Type: text/plain; charset="utf-8" Instead of special casing the permission handling and watch event firing for the special watch paths "@introduceDomain" and "@releaseDomain", use static dummy nodes added to the data base when starting Xenstore. The node accounting needs to reflect that change by adding the special nodes in the domain_entry_fix() call in setup_structure(). Note that this requires to rework the calls of fire_watches() for the special events in order to avoid leaking memory. Move the check for a valid node name from get_node() to get_node_canonicalized(), as it allows to use get_node() for the special nodes, too. In order to avoid read and write accesses to the special nodes use a special variant for obtaining the current node data for the permission handling. This allows to simplify quite some code. In future sub-nodes of the special nodes will be possible due to this change, allowing more fine grained permission control of special events for specific domains. Signed-off-by: Juergen Gross --- V2: - add get_spec_node() - expand commit message (Julien Grall) --- tools/xenstore/xenstored_control.c | 3 - tools/xenstore/xenstored_core.c | 92 +++++++++------- tools/xenstore/xenstored_domain.c | 162 ++++------------------------- tools/xenstore/xenstored_domain.h | 6 -- tools/xenstore/xenstored_watch.c | 17 +-- 5 files changed, 80 insertions(+), 200 deletions(-) diff --git a/tools/xenstore/xenstored_control.c b/tools/xenstore/xenstored_= control.c index d1aaa00bf4..41e6992591 100644 --- a/tools/xenstore/xenstored_control.c +++ b/tools/xenstore/xenstored_control.c @@ -676,9 +676,6 @@ static const char *lu_dump_state(const void *ctx, struc= t connection *conn) if (ret) goto out; ret =3D dump_state_connections(fp); - if (ret) - goto out; - ret =3D dump_state_special_nodes(fp); if (ret) goto out; ret =3D dump_state_nodes(fp, ctx); diff --git a/tools/xenstore/xenstored_core.c b/tools/xenstore/xenstored_cor= e.c index 1650821922..f96714e1b8 100644 --- a/tools/xenstore/xenstored_core.c +++ b/tools/xenstore/xenstored_core.c @@ -616,7 +616,8 @@ static void get_acc_data(TDB_DATA *key, struct node_acc= ount_data *acc) static unsigned int get_acc_domid(struct connection *conn, TDB_DATA *key, unsigned int domid) { - return (!conn || key->dptr[0] =3D=3D '/') ? domid : conn->id; + return (!conn || key->dptr[0] =3D=3D '/' || key->dptr[0] =3D=3D '@') + ? domid : conn->id; } =20 int do_tdb_write(struct connection *conn, TDB_DATA *key, TDB_DATA *data, @@ -958,10 +959,6 @@ static struct node *get_node(struct connection *conn, { struct node *node; =20 - if (!name || !is_valid_nodename(name)) { - errno =3D EINVAL; - return NULL; - } node =3D read_node(conn, ctx, name); /* If we don't have permission, we don't have node. */ if (node) { @@ -1250,9 +1247,23 @@ static struct node *get_node_canonicalized(struct co= nnection *conn, *canonical_name =3D canonicalize(conn, ctx, name); if (!*canonical_name) return NULL; + if (!is_valid_nodename(*canonical_name)) { + errno =3D EINVAL; + return NULL; + } return get_node(conn, ctx, *canonical_name, perm); } =20 +static struct node *get_spec_node(struct connection *conn, const void *ctx, + const char *name, char **canonical_name, + unsigned int perm) +{ + if (name[0] =3D=3D '@') + return get_node(conn, ctx, name, perm); + + return get_node_canonicalized(conn, ctx, name, canonical_name, perm); +} + static int send_directory(const void *ctx, struct connection *conn, struct buffered_data *in) { @@ -1737,8 +1748,7 @@ static int do_get_perms(const void *ctx, struct conne= ction *conn, char *strings; unsigned int len; =20 - node =3D get_node_canonicalized(conn, ctx, onearg(in), NULL, - XS_PERM_READ); + node =3D get_spec_node(conn, ctx, onearg(in), NULL, XS_PERM_READ); if (!node) return errno; =20 @@ -1780,17 +1790,9 @@ static int do_set_perms(const void *ctx, struct conn= ection *conn, if (perms.p[0].perms & XS_PERM_IGNORE) return ENOENT; =20 - /* First arg is node name. */ - if (strstarts(in->buffer, "@")) { - if (set_perms_special(conn, in->buffer, &perms)) - return errno; - send_ack(conn, XS_SET_PERMS); - return 0; - } - /* We must own node to do this (tools can do this too). */ - node =3D get_node_canonicalized(conn, ctx, in->buffer, &name, - XS_PERM_WRITE | XS_PERM_OWNER); + node =3D get_spec_node(conn, ctx, in->buffer, &name, + XS_PERM_WRITE | XS_PERM_OWNER); if (!node) return errno; =20 @@ -2388,7 +2390,9 @@ void setup_structure(bool live_update) manual_node("/", "tool"); manual_node("/tool", "xenstored"); manual_node("/tool/xenstored", NULL); - domain_entry_fix(dom0_domid, 3, true); + manual_node("@releaseDomain", NULL); + manual_node("@introduceDomain", NULL); + domain_entry_fix(dom0_domid, 5, true); } =20 check_store(); @@ -3170,6 +3174,23 @@ static int dump_state_node(const void *ctx, struct c= onnection *conn, return WALK_TREE_OK; } =20 +static int dump_state_special_node(FILE *fp, const void *ctx, + struct dump_node_data *data, + const char *name) +{ + struct node *node; + int ret; + + node =3D read_node(NULL, ctx, name); + if (!node) + return dump_state_node_err(data, "Dump node read node error"); + + ret =3D dump_state_node(ctx, NULL, node, data); + talloc_free(node); + + return ret; +} + const char *dump_state_nodes(FILE *fp, const void *ctx) { struct dump_node_data data =3D { @@ -3181,6 +3202,11 @@ const char *dump_state_nodes(FILE *fp, const void *c= tx) if (walk_node_tree(ctx, NULL, "/", &walkfuncs, &data)) return data.err; =20 + if (dump_state_special_node(fp, ctx, &data, "@releaseDomain")) + return data.err; + if (dump_state_special_node(fp, ctx, &data, "@introduceDomain")) + return data.err; + return NULL; } =20 @@ -3354,25 +3380,21 @@ void read_state_node(const void *ctx, const void *s= tate) node->perms.p[i].id =3D sn->perms[i].domid; } =20 - if (strstarts(name, "@")) { - set_perms_special(&conn, name, &node->perms); - talloc_free(node); - return; - } - - parentname =3D get_parent(node, name); - if (!parentname) - barf("allocation error restoring node"); - parent =3D read_node(NULL, node, parentname); - if (!parent) - barf("read parent error restoring node"); + if (!strstarts(name, "@")) { + parentname =3D get_parent(node, name); + if (!parentname) + barf("allocation error restoring node"); + parent =3D read_node(NULL, node, parentname); + if (!parent) + barf("read parent error restoring node"); =20 - if (add_child(node, parent, name)) - barf("allocation error restoring node"); + if (add_child(node, parent, name)) + barf("allocation error restoring node"); =20 - set_tdb_key(parentname, &key); - if (write_node_raw(NULL, &key, parent, true)) - barf("write parent error restoring node"); + set_tdb_key(parentname, &key); + if (write_node_raw(NULL, &key, parent, true)) + barf("write parent error restoring node"); + } =20 set_tdb_key(name, &key); if (write_node_raw(NULL, &key, node, true)) diff --git a/tools/xenstore/xenstored_domain.c b/tools/xenstore/xenstored_d= omain.c index 3ad1028edb..c881c93d1d 100644 --- a/tools/xenstore/xenstored_domain.c +++ b/tools/xenstore/xenstored_domain.c @@ -43,9 +43,6 @@ static evtchn_port_t virq_port; =20 xenevtchn_handle *xce_handle =3D NULL; =20 -static struct node_perms dom_release_perms; -static struct node_perms dom_introduce_perms; - struct domain { /* The id of this domain */ @@ -225,27 +222,6 @@ static void unmap_interface(void *interface) xengnttab_unmap(*xgt_handle, interface, 1); } =20 -static void remove_domid_from_perm(struct node_perms *perms, - struct domain *domain) -{ - unsigned int cur, new; - - if (perms->p[0].id =3D=3D domain->domid) - perms->p[0].id =3D priv_domid; - - for (cur =3D new =3D 1; cur < perms->num; cur++) { - if (perms->p[cur].id =3D=3D domain->domid) - continue; - - if (new !=3D cur) - perms->p[new] =3D perms->p[cur]; - - new++; - } - - perms->num =3D new; -} - static int domain_tree_remove_sub(const void *ctx, struct connection *conn, struct node *node, void *arg) { @@ -297,8 +273,24 @@ static void domain_tree_remove(struct domain *domain) "error when looking for orphaned nodes\n"); } =20 - remove_domid_from_perm(&dom_release_perms, domain); - remove_domid_from_perm(&dom_introduce_perms, domain); + walk_node_tree(domain, NULL, "@releaseDomain", &walkfuncs, domain); + walk_node_tree(domain, NULL, "@introduceDomain", &walkfuncs, domain); +} + +static void fire_special_watches(const char *name) +{ + void *ctx =3D talloc_new(NULL); + struct node *node; + + if (!ctx) + return; + + node =3D read_node(NULL, ctx, name); + + if (node) + fire_watches(NULL, ctx, name, node, true, NULL); + + talloc_free(ctx); } =20 static int destroy_domain(void *_domain) @@ -326,7 +318,7 @@ static int destroy_domain(void *_domain) unmap_interface(domain->interface); } =20 - fire_watches(NULL, domain, "@releaseDomain", NULL, true, NULL); + fire_special_watches("@releaseDomain"); =20 wrl_domain_destroy(domain); =20 @@ -384,7 +376,7 @@ void check_domains(void) ; =20 if (notify) - fire_watches(NULL, NULL, "@releaseDomain", NULL, true, NULL); + fire_special_watches("@releaseDomain"); } =20 /* We scan all domains rather than use the information given here. */ @@ -633,8 +625,7 @@ static struct domain *introduce_domain(const void *ctx, } =20 if (!is_master_domain && !restore) - fire_watches(NULL, ctx, "@introduceDomain", NULL, - true, NULL); + fire_special_watches("@introduceDomain"); } else { /* Use XS_INTRODUCE for recreating the xenbus event-channel. */ if (domain->port) @@ -840,59 +831,6 @@ const char *get_implicit_path(const struct connection = *conn) return conn->domain->path; } =20 -static int set_dom_perms_default(struct node_perms *perms) -{ - perms->num =3D 1; - perms->p =3D talloc_array(NULL, struct xs_permissions, perms->num); - if (!perms->p) - return -1; - perms->p->id =3D 0; - perms->p->perms =3D XS_PERM_NONE; - - return 0; -} - -static struct node_perms *get_perms_special(const char *name) -{ - if (!strcmp(name, "@releaseDomain")) - return &dom_release_perms; - if (!strcmp(name, "@introduceDomain")) - return &dom_introduce_perms; - return NULL; -} - -int set_perms_special(struct connection *conn, const char *name, - struct node_perms *perms) -{ - struct node_perms *p; - - p =3D get_perms_special(name); - if (!p) - return EINVAL; - - if ((perm_for_conn(conn, p) & (XS_PERM_WRITE | XS_PERM_OWNER)) !=3D - (XS_PERM_WRITE | XS_PERM_OWNER)) - return EACCES; - - p->num =3D perms->num; - talloc_free(p->p); - p->p =3D perms->p; - talloc_steal(NULL, perms->p); - - return 0; -} - -bool check_perms_special(const char *name, struct connection *conn) -{ - struct node_perms *p; - - p =3D get_perms_special(name); - if (!p) - return false; - - return perm_for_conn(conn, p) & XS_PERM_READ; -} - void dom0_init(void) { evtchn_port_t port; @@ -962,10 +900,6 @@ void domain_init(int evtfd) if (xce_handle =3D=3D NULL) barf_perror("Failed to open evtchn device"); =20 - if (set_dom_perms_default(&dom_release_perms) || - set_dom_perms_default(&dom_introduce_perms)) - barf_perror("Failed to set special permissions"); - if ((rc =3D xenevtchn_bind_virq(xce_handle, VIRQ_DOM_EXC)) =3D=3D -1) barf_perror("Failed to bind to domain exception virq port"); virq_port =3D rc; @@ -1535,60 +1469,6 @@ const char *dump_state_connections(FILE *fp) return ret; } =20 -static const char *dump_state_special_node(FILE *fp, const char *name, - const struct node_perms *perms) -{ - struct xs_state_record_header head; - struct xs_state_node sn; - unsigned int pathlen; - const char *ret; - - pathlen =3D strlen(name) + 1; - - head.type =3D XS_STATE_TYPE_NODE; - head.length =3D sizeof(sn); - - sn.conn_id =3D 0; - sn.ta_id =3D 0; - sn.ta_access =3D 0; - sn.perm_n =3D perms->num; - sn.path_len =3D pathlen; - sn.data_len =3D 0; - head.length +=3D perms->num * sizeof(*sn.perms); - head.length +=3D pathlen; - head.length =3D ROUNDUP(head.length, 3); - if (fwrite(&head, sizeof(head), 1, fp) !=3D 1) - return "Dump special node error"; - if (fwrite(&sn, sizeof(sn), 1, fp) !=3D 1) - return "Dump special node error"; - - ret =3D dump_state_node_perms(fp, perms->p, perms->num); - if (ret) - return ret; - - if (fwrite(name, pathlen, 1, fp) !=3D 1) - return "Dump special node path error"; - - ret =3D dump_state_align(fp); - - return ret; -} - -const char *dump_state_special_nodes(FILE *fp) -{ - const char *ret; - - ret =3D dump_state_special_node(fp, "@releaseDomain", - &dom_release_perms); - if (ret) - return ret; - - ret =3D dump_state_special_node(fp, "@introduceDomain", - &dom_introduce_perms); - - return ret; -} - void read_state_connection(const void *ctx, const void *state) { const struct xs_state_connection *sc =3D state; diff --git a/tools/xenstore/xenstored_domain.h b/tools/xenstore/xenstored_d= omain.h index b38c82991d..630641d620 100644 --- a/tools/xenstore/xenstored_domain.h +++ b/tools/xenstore/xenstored_domain.h @@ -99,11 +99,6 @@ void domain_outstanding_domid_dec(unsigned int domid); int domain_get_quota(const void *ctx, struct connection *conn, unsigned int domid); =20 -/* Special node permission handling. */ -int set_perms_special(struct connection *conn, const char *name, - struct node_perms *perms); -bool check_perms_special(const char *name, struct connection *conn); - /* Write rate limiting */ =20 #define WRL_FACTOR 1000 /* for fixed-point arithmetic */ @@ -132,7 +127,6 @@ void wrl_apply_debit_direct(struct connection *conn); void wrl_apply_debit_trans_commit(struct connection *conn); =20 const char *dump_state_connections(FILE *fp); -const char *dump_state_special_nodes(FILE *fp); =20 void read_state_connection(const void *ctx, const void *state); =20 diff --git a/tools/xenstore/xenstored_watch.c b/tools/xenstore/xenstored_wa= tch.c index 316c08b7f7..75748ac109 100644 --- a/tools/xenstore/xenstored_watch.c +++ b/tools/xenstore/xenstored_watch.c @@ -46,13 +46,6 @@ struct watch char *node; }; =20 -static bool check_special_event(const char *name) -{ - assert(name); - - return strstarts(name, "@"); -} - /* Is child a subnode of parent, or equal? */ static bool is_child(const char *child, const char *parent) { @@ -153,14 +146,8 @@ void fire_watches(struct connection *conn, const void = *ctx, const char *name, =20 /* Create an event for each watch. */ list_for_each_entry(i, &connections, list) { - /* introduce/release domain watches */ - if (check_special_event(name)) { - if (!check_perms_special(name, i)) - continue; - } else { - if (!watch_permitted(i, ctx, name, node, perms)) - continue; - } + if (!watch_permitted(i, ctx, name, node, perms)) + continue; =20 list_for_each_entry(watch, &i->watches, list) { if (exact) { --=20 2.35.3