From nobody Thu Dec 18 09:59:25 2025 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; 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=fail(p=none dis=none) header.from=arm.com Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1765824065622318.3687292961929; Mon, 15 Dec 2025 10:41:05 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1187132.1508583 (Exim 4.92) (envelope-from ) id 1vV9tm-0004sH-Vf; Mon, 15 Dec 2025 14:50:06 +0000 Received: by outflank-mailman (output) from mailman id 1187132.1508583; Mon, 15 Dec 2025 14:50: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 1vV9tm-0004rp-QV; Mon, 15 Dec 2025 14:50:06 +0000 Received: by outflank-mailman (input) for mailman id 1187132; Mon, 15 Dec 2025 14:50:05 +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 1vV9tl-00038W-1G for xen-devel@lists.xenproject.org; Mon, 15 Dec 2025 14:50:05 +0000 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by se1-gles-flk1.inumbo.com (Halon) with ESMTP id 564167ba-d9c5-11f0-9cce-f158ae23cfc8; Mon, 15 Dec 2025 15:50:03 +0100 (CET) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 2711F497; Mon, 15 Dec 2025 06:49:55 -0800 (PST) Received: from C3HXLD123V.arm.com (unknown [10.57.46.206]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 33BD23F694; Mon, 15 Dec 2025 06:50:01 -0800 (PST) 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: 564167ba-d9c5-11f0-9cce-f158ae23cfc8 From: Bertrand Marquis To: xen-devel@lists.xenproject.org Cc: jens.wiklander@linaro.org, Volodymyr Babchuk , Stefano Stabellini , Julien Grall , Michal Orzel Subject: [PATCH v2 04/12] xen/arm: ffa: harden RX/TX mapping Date: Mon, 15 Dec 2025 15:49:21 +0100 Message-ID: <5c8d22e3c3db0a62aa14f000fe4867614bc78456.1765807707.git.bertrand.marquis@arm.com> X-Mailer: git-send-email 2.51.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1765824067289158500 Content-Type: text/plain; charset="utf-8" Harden the RX/TX mapping paths and keep signed FF-A return codes end-to-end. Reject zero-length mappings and insist on page-aligned RX/TX buffer addresses before touching the P2M. The unmap plumbing is switched to use the same signed helpers so dispatcher error handling is consistent across map and unmap operations. This avoids partially mapped or silently truncated buffers and makes the mediator behaviour match the FF-A error model more closely. Prevent concurrent usage of rx or tx buffer during map or unmap by holding the rx_lock and tx_lock. While there also introduce a domain_rxtx_init to properly initialize the rxtx buffers spinlocks. Signed-off-by: Bertrand Marquis Reviewed-by: Jens Wiklander --- Changes in v2: - add Jens R-b Changes in v1: - take the rx_lock and tx_lock during rxtx_map and rxtx_unmap to prevent concurrent calls using the rx or tx buffer during mapping. - properly clean rx/tx buffer related context entries during domain_init --- xen/arch/arm/tee/ffa.c | 4 ++ xen/arch/arm/tee/ffa_private.h | 5 ++- xen/arch/arm/tee/ffa_rxtx.c | 68 +++++++++++++++++++++++++++------- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c index 0f6f837378cc..497ada8264e0 100644 --- a/xen/arch/arm/tee/ffa.c +++ b/xen/arch/arm/tee/ffa.c @@ -451,6 +451,10 @@ static int ffa_domain_init(struct domain *d) if ( ret ) return ret; =20 + ret =3D ffa_rxtx_domain_init(d); + if ( ret ) + return ret; + return ffa_notif_domain_init(d); } =20 diff --git a/xen/arch/arm/tee/ffa_private.h b/xen/arch/arm/tee/ffa_private.h index 96794ecebe4b..0bb5a84553ce 100644 --- a/xen/arch/arm/tee/ffa_private.h +++ b/xen/arch/arm/tee/ffa_private.h @@ -439,10 +439,11 @@ void ffa_handle_partition_info_get(struct cpu_user_re= gs *regs); =20 bool ffa_rxtx_init(void); void ffa_rxtx_destroy(void); +int32_t ffa_rxtx_domain_init(struct domain *d); void ffa_rxtx_domain_destroy(struct domain *d); -uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, +int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, register_t rx_addr, uint32_t page_count); -uint32_t ffa_handle_rxtx_unmap(void); +int32_t ffa_handle_rxtx_unmap(void); int32_t ffa_rx_acquire(struct domain *d); int32_t ffa_rx_release(struct domain *d); =20 diff --git a/xen/arch/arm/tee/ffa_rxtx.c b/xen/arch/arm/tee/ffa_rxtx.c index a40e5b32e3a5..5776693bb3f0 100644 --- a/xen/arch/arm/tee/ffa_rxtx.c +++ b/xen/arch/arm/tee/ffa_rxtx.c @@ -41,10 +41,10 @@ static int32_t ffa_rxtx_unmap(uint16_t id) return ffa_simple_call(FFA_RXTX_UNMAP, ((uint64_t)id) << 16, 0, 0, 0); } =20 -uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, +int32_t ffa_handle_rxtx_map(uint32_t fid, register_t tx_addr, register_t rx_addr, uint32_t page_count) { - uint32_t ret =3D FFA_RET_INVALID_PARAMETERS; + int32_t ret =3D FFA_RET_INVALID_PARAMETERS; struct domain *d =3D current->domain; struct ffa_ctx *ctx =3D d->arch.tee; struct page_info *tx_pg; @@ -66,20 +66,30 @@ uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t t= x_addr, rx_addr &=3D UINT32_MAX; } =20 - if ( page_count > FFA_MAX_RXTX_PAGE_COUNT ) + if ( page_count > FFA_MAX_RXTX_PAGE_COUNT || !page_count ) { printk(XENLOG_ERR "ffa: RXTX_MAP: error: %u pages requested (limit= %u)\n", page_count, FFA_MAX_RXTX_PAGE_COUNT); return FFA_RET_INVALID_PARAMETERS; } =20 + if ( !IS_ALIGNED(tx_addr, FFA_PAGE_SIZE) || + !IS_ALIGNED(rx_addr, FFA_PAGE_SIZE) ) + return FFA_RET_INVALID_PARAMETERS; + + spin_lock(&ctx->rx_lock); + spin_lock(&ctx->tx_lock); + /* Already mapped */ if ( ctx->rx ) - return FFA_RET_DENIED; + { + ret =3D FFA_RET_DENIED; + goto err_unlock_rxtx; + } =20 tx_pg =3D get_page_from_gfn(d, gfn_x(gaddr_to_gfn(tx_addr)), &t, P2M_A= LLOC); if ( !tx_pg ) - return FFA_RET_INVALID_PARAMETERS; + goto err_unlock_rxtx; =20 /* Only normal RW RAM for now */ if ( t !=3D p2m_ram_rw ) @@ -167,6 +177,10 @@ uint32_t ffa_handle_rxtx_map(uint32_t fid, register_t = tx_addr, ctx->tx_pg =3D tx_pg; ctx->page_count =3D page_count; ctx->rx_is_free =3D true; + + spin_unlock(&ctx->tx_lock); + spin_unlock(&ctx->rx_lock); + return FFA_RET_OK; =20 err_unmap_rx: @@ -177,24 +191,32 @@ err_put_rx_pg: put_page(rx_pg); err_put_tx_pg: put_page(tx_pg); +err_unlock_rxtx: + spin_unlock(&ctx->tx_lock); + spin_unlock(&ctx->rx_lock); =20 return ret; } =20 -static uint32_t rxtx_unmap(struct domain *d) +static int32_t rxtx_unmap(struct domain *d) { struct ffa_ctx *ctx =3D d->arch.tee; + int32_t ret =3D FFA_RET_OK; + + spin_lock(&ctx->rx_lock); + spin_lock(&ctx->tx_lock); =20 if ( !ctx->page_count ) - return FFA_RET_INVALID_PARAMETERS; + { + ret =3D FFA_RET_INVALID_PARAMETERS; + goto err_unlock_rxtx; + } =20 if ( ffa_fw_supports_fid(FFA_RX_ACQUIRE) ) { - uint32_t ret; - ret =3D ffa_rxtx_unmap(ffa_get_vm_id(d)); if ( ret !=3D FFA_RET_OK ) - return ret; + goto err_unlock_rxtx; } =20 unmap_domain_page_global(ctx->rx); @@ -208,10 +230,14 @@ static uint32_t rxtx_unmap(struct domain *d) ctx->page_count =3D 0; ctx->rx_is_free =3D false; =20 - return FFA_RET_OK; +err_unlock_rxtx: + spin_unlock(&ctx->tx_lock); + spin_unlock(&ctx->rx_lock); + + return ret; } =20 -uint32_t ffa_handle_rxtx_unmap(void) +int32_t ffa_handle_rxtx_unmap(void) { return rxtx_unmap(current->domain); } @@ -272,6 +298,22 @@ out: return ret; } =20 +int32_t ffa_rxtx_domain_init(struct domain *d) +{ + struct ffa_ctx *ctx =3D d->arch.tee; + + spin_lock_init(&ctx->rx_lock); + spin_lock_init(&ctx->tx_lock); + ctx->rx =3D NULL; + ctx->tx =3D NULL; + ctx->rx_pg =3D NULL; + ctx->tx_pg =3D NULL; + ctx->page_count =3D 0; + ctx->rx_is_free =3D false; + + return 0; +} + void ffa_rxtx_domain_destroy(struct domain *d) { rxtx_unmap(d); @@ -298,7 +340,7 @@ void ffa_rxtx_destroy(void) =20 bool ffa_rxtx_init(void) { - int e; + int32_t e; =20 /* Firmware not there or not supporting */ if ( !ffa_fw_supports_fid(FFA_RXTX_MAP_64) ) --=20 2.51.2