From nobody Wed Apr 24 12:14:05 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=1633340438; cv=none; d=zohomail.com; s=zohoarc; b=HWcUSnLCR3gfxDhNrbAKnWzhz7o2t/JOLaD9y+SPzLQMXMDMoWrFcDvyhNrm83/4VTrQFtA27AxDV2ZPwvgyybxd11bpeOcqMUgxXvWAFxm64kuM5CkB0bHXi9e6Dv2R4rTU82dw7I+86mNYTfAoG1CF175Xaq8vk+4LHzWoKYg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1633340438; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=2fFPIPlC+atciMa/6CO3r585X3XUQbQXFh8lKdi63pg=; b=fdvU5y07K5s5diFI9BG/8TioQar//9fY5bY1cj7C94oQpEGtCvSp6WAKsoQABUC3bEVXRquu1pVUnSLTrs77A70X/MRB4oagPrsgU4O1VHS/itMtgrQSAvfN2LcSXL7bOKZkOwrGBCUgmm7SCVNGUuIH4LXHfTFpYa/ihFkvJOQ= 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 1633340438804887.3953949281087; Mon, 4 Oct 2021 02:40:38 -0700 (PDT) Received: from list by lists.xenproject.org with outflank-mailman.201244.355671 (Exim 4.92) (envelope-from ) id 1mXKS6-000272-QP; Mon, 04 Oct 2021 09:40:06 +0000 Received: by outflank-mailman (output) from mailman id 201244.355671; Mon, 04 Oct 2021 09:40:06 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mXKS6-00026v-NS; Mon, 04 Oct 2021 09:40:06 +0000 Received: by outflank-mailman (input) for mailman id 201244; Mon, 04 Oct 2021 09:40:05 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1mXKS5-00024g-IZ for xen-devel@lists.xenproject.org; Mon, 04 Oct 2021 09:40:05 +0000 Received: from smtp-out2.suse.de (unknown [195.135.220.29]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 0c309f9c-24f7-11ec-bea7-12813bfff9fa; Mon, 04 Oct 2021 09:40:02 +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 smtp-out2.suse.de (Postfix) with ESMTPS id CADA62019A; Mon, 4 Oct 2021 09:40:01 +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 9787A13A13; Mon, 4 Oct 2021 09:40:01 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id /oXMI/HLWmG5RAAAMHmgww (envelope-from ); Mon, 04 Oct 2021 09:40:01 +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: 0c309f9c-24f7-11ec-bea7-12813bfff9fa DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1633340401; 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; bh=2fFPIPlC+atciMa/6CO3r585X3XUQbQXFh8lKdi63pg=; b=fl0U3dzb+07pemGi4N7J3gF5T+LVvmLKYcoGqCxtVVtGrYkT7V6oTkEyIcz1mH1CxsLooO 0JG7aiedEVgf9JI6KPA/IY19M1Q9O8l7xrUI/tESKvw5rP8rYFWKzp4umKyo8MjDl9P05k DGouRhytjCBn19afksaVzJBTnXNaz+Y= From: Juergen Gross To: minios-devel@lists.xenproject.org, xen-devel@lists.xenproject.org Cc: samuel.thibault@ens-lyon.org, wl@xen.org, Juergen Gross Subject: [PATCH v4] xenbus: support large messages Date: Mon, 4 Oct 2021 11:40:00 +0200 Message-Id: <20211004094000.29868-1-jgross@suse.com> X-Mailer: git-send-email 2.26.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @suse.com) X-ZM-MESSAGEID: 1633340440842100001 Content-Type: text/plain; charset="utf-8" Today the implementation of the xenbus protocol in Mini-OS will only allow to transfer the complete message to or from the ring page buffer. This is limiting the maximum message size to lower values as the xenbus protocol normally would allow. Change that by allowing to transfer the xenbus message in chunks as soon as they are available. Avoid crashing Mini-OS in case of illegal data read from the ring buffer. Signed-off-by: Juergen Gross Reviewed-by: Samuel Thibault --- V2: - drop redundant if (Samuel Thibault) - move rmb() (Samuel Thibault) V3: - correct notification test (Samuel Thibault) V4: - more memory barriers (Samuel Thibault) --- xenbus/xenbus.c | 210 ++++++++++++++++++++++++++++-------------------- 1 file changed, 122 insertions(+), 88 deletions(-) diff --git a/xenbus/xenbus.c b/xenbus/xenbus.c index 23de61e..b687678 100644 --- a/xenbus/xenbus.c +++ b/xenbus/xenbus.c @@ -29,6 +29,7 @@ #include #include #include +#include =20 #define min(x,y) ({ \ typeof(x) tmpx =3D (x); \ @@ -46,6 +47,7 @@ static struct xenstore_domain_interface *xenstore_buf; static DECLARE_WAIT_QUEUE_HEAD(xb_waitq); DECLARE_WAIT_QUEUE_HEAD(xenbus_watch_queue); +static __DECLARE_SEMAPHORE_GENERIC(xb_write_sem, 1); =20 xenbus_event_queue xenbus_events; static struct watch { @@ -231,75 +233,103 @@ char *xenbus_wait_for_state_change(const char* path,= XenbusState *state, xenbus_ } =20 =20 +static void xenbus_read_data(char *buf, unsigned int len) +{ + unsigned int off =3D 0; + unsigned int prod, cons; + unsigned int size; + + while (off !=3D len) + { + wait_event(xb_waitq, xenstore_buf->rsp_prod !=3D xenstore_buf->rsp= _cons); + + prod =3D xenstore_buf->rsp_prod; + cons =3D xenstore_buf->rsp_cons; + DEBUG("Rsp_cons %d, rsp_prod %d.\n", cons, prod); + size =3D min(len - off, prod - cons); + + rmb(); /* Make sure data read from ring is ordered with rsp_prod= . */ + memcpy_from_ring(xenstore_buf->rsp, buf + off, + MASK_XENSTORE_IDX(cons), size); + off +=3D size; + mb(); /* memcpy() and rsp_cons update must not be reordered. */ + xenstore_buf->rsp_cons +=3D size; + mb(); /* rsp_cons must be visible before we look at rsp_prod. */ + if (xenstore_buf->rsp_prod - cons >=3D XENSTORE_RING_SIZE) + notify_remote_via_evtchn(xenbus_evtchn); + } +} + static void xenbus_thread_func(void *ign) { struct xsd_sockmsg msg; - unsigned prod =3D xenstore_buf->rsp_prod; + char *data; =20 for (;;) { - wait_event(xb_waitq, prod !=3D xenstore_buf->rsp_prod); - while (1) { - prod =3D xenstore_buf->rsp_prod; - DEBUG("Rsp_cons %d, rsp_prod %d.\n", xenstore_buf->rsp_cons, - xenstore_buf->rsp_prod); - if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < sizeof(m= sg)) - break; - rmb(); - memcpy_from_ring(xenstore_buf->rsp, &msg, - MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), - sizeof(msg)); - DEBUG("Msg len %d, %d avail, id %d.\n", msg.len + sizeof(msg), - xenstore_buf->rsp_prod - xenstore_buf->rsp_cons, msg.req= _id); - - if (xenstore_buf->rsp_prod - xenstore_buf->rsp_cons < - sizeof(msg) + msg.len) - break; - - DEBUG("Message is good.\n"); - - if (msg.type =3D=3D XS_WATCH_EVENT) { - struct xenbus_event *event =3D malloc(sizeof(*event) + msg= .len); - xenbus_event_queue *events =3D NULL; - char *data =3D (char*)event + sizeof(*event); - struct watch *watch; - - memcpy_from_ring(xenstore_buf->rsp, data, - MASK_XENSTORE_IDX(xenstore_buf->rsp_cons + sizeof(msg)= ), - msg.len); - - event->path =3D data; - event->token =3D event->path + strlen(event->path) + 1; - - mb(); - xenstore_buf->rsp_cons +=3D msg.len + sizeof(msg); - - for (watch =3D watches; watch; watch =3D watch->next) - if (!strcmp(watch->token, event->token)) { - events =3D watch->events; - break; - } - - if (events) { - event->next =3D *events; - *events =3D event; - wake_up(&xenbus_watch_queue); - } else { - printk("unexpected watch token %s\n", event->token); - free(event); + xenbus_read_data((char *)&msg, sizeof(msg)); + DEBUG("Msg len %d, %d avail, id %d.\n", msg.len + sizeof(msg), + xenstore_buf->rsp_prod - xenstore_buf->rsp_cons, msg.req_id); + + if (msg.len > XENSTORE_PAYLOAD_MAX) { + printk("Xenstore violates protocol, message longer than allowe= d.\n"); + return; + } + + if (msg.type =3D=3D XS_WATCH_EVENT) { + struct xenbus_event *event =3D malloc(sizeof(*event) + msg.len= ); + xenbus_event_queue *events =3D NULL; + struct watch *watch; + char *c; + int zeroes =3D 0; + + data =3D (char*)event + sizeof(*event); + xenbus_read_data(data, msg.len); + + for (c =3D data; c < data + msg.len; c++) + if (!*c) + zeroes++; + if (zeroes !=3D 2) { + printk("Xenstore: illegal watch event data\n"); + free(event); + continue; + } + + event->path =3D data; + event->token =3D event->path + strlen(event->path) + 1; + + for (watch =3D watches; watch; watch =3D watch->next) + if (!strcmp(watch->token, event->token)) { + events =3D watch->events; + break; } + + if (events) { + event->next =3D *events; + *events =3D event; + wake_up(&xenbus_watch_queue); } else { - req_info[msg.req_id].reply =3D malloc(sizeof(msg) + msg.le= n); - memcpy_from_ring(xenstore_buf->rsp, req_info[msg.req_id].r= eply, - MASK_XENSTORE_IDX(xenstore_buf->rsp_cons), - msg.len + sizeof(msg)); - mb(); - xenstore_buf->rsp_cons +=3D msg.len + sizeof(msg); - wake_up(&req_info[msg.req_id].waitq); + printk("Xenstore: unexpected watch token %s\n", event->tok= en); + free(event); } =20 - wmb(); - notify_remote_via_evtchn(xenbus_evtchn); + continue; } + + data =3D malloc(sizeof(msg) + msg.len); + memcpy(data, &msg, sizeof(msg)); + xenbus_read_data(data + sizeof(msg), msg.len); + + if (msg.req_id >=3D NR_REQS || !req_info[msg.req_id].in_use) { + printk("Xenstore: illegal request id %d\n", msg.req_id); + free(data); + continue; + } + + DEBUG("Message is good.\n"); + + req_info[msg.req_id].reply =3D data; + + wake_up(&req_info[msg.req_id].waitq); } } =20 @@ -451,36 +481,40 @@ static void xb_write(int type, int req_id, xenbus_tra= nsaction_t trans_id, =20 cur_req =3D &header_req; =20 - BUG_ON(len > XENSTORE_RING_SIZE); - /* Wait for the ring to drain to the point where we can send the - message. */ - prod =3D xenstore_buf->req_prod; - if (prod + len - xenstore_buf->req_cons > XENSTORE_RING_SIZE)=20 - { - /* Wait for there to be space on the ring */ - DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n", - prod, len, xenstore_buf->req_cons, XENSTORE_RING_SIZE); - wait_event(xb_waitq, - xenstore_buf->req_prod + len - xenstore_buf->req_cons <=3D - XENSTORE_RING_SIZE); - DEBUG("Back from wait.\n"); - prod =3D xenstore_buf->req_prod; - } + BUG_ON(len > XENSTORE_PAYLOAD_MAX); + + /* Make sure we are the only thread trying to write. */ + down(&xb_write_sem); =20 - /* We're now guaranteed to be able to send the message without - overflowing the ring. Do so. */ + /* Send the message in chunks using free ring space when available. */ total_off =3D 0; req_off =3D 0; - while (total_off < len)=20 + while (total_off < len) { + prod =3D xenstore_buf->req_prod; + if (prod - xenstore_buf->req_cons >=3D XENSTORE_RING_SIZE) + { + /* Send evtchn to notify remote */ + notify_remote_via_evtchn(xenbus_evtchn); + + /* Wait for there to be space on the ring */ + DEBUG("prod %d, len %d, cons %d, size %d; waiting.\n", prod, + len - total_off, xenstore_buf->req_cons, XENSTORE_RING_S= IZE); + wait_event(xb_waitq, + prod - xenstore_buf->req_cons < XENSTORE_RING_SIZE); + DEBUG("Back from wait.\n"); + } + this_chunk =3D min(cur_req->len - req_off, - XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); + XENSTORE_RING_SIZE - MASK_XENSTORE_IDX(prod)); + this_chunk =3D min(this_chunk, + xenstore_buf->req_cons + XENSTORE_RING_SIZE - pro= d); memcpy((char *)xenstore_buf->req + MASK_XENSTORE_IDX(prod), - (char *)cur_req->data + req_off, this_chunk); + (char *)cur_req->data + req_off, this_chunk); prod +=3D this_chunk; req_off +=3D this_chunk; total_off +=3D this_chunk; - if (req_off =3D=3D cur_req->len)=20 + if (req_off =3D=3D cur_req->len) { req_off =3D 0; if (cur_req =3D=3D &header_req) @@ -488,20 +522,20 @@ static void xb_write(int type, int req_id, xenbus_tra= nsaction_t trans_id, else cur_req++; } + + /* Remote must see entire message before updating indexes */ + wmb(); + xenstore_buf->req_prod =3D prod; } =20 + /* Send evtchn to notify remote */ + notify_remote_via_evtchn(xenbus_evtchn); + DEBUG("Complete main loop of xb_write.\n"); BUG_ON(req_off !=3D 0); BUG_ON(total_off !=3D len); - BUG_ON(prod > xenstore_buf->req_cons + XENSTORE_RING_SIZE); =20 - /* Remote must see entire message before updating indexes */ - wmb(); - - xenstore_buf->req_prod +=3D len; - - /* Send evtchn to notify remote */ - notify_remote_via_evtchn(xenbus_evtchn); + up(&xb_write_sem); } =20 /* Send a mesasge to xenbus, in the same fashion as xb_write, and --=20 2.26.2