Hi Bertrand,

On Fri, Dec 5, 2025 at 11:37 AM Bertrand Marquis
<[email protected]> wrote:
>
> Teach the SEND2 path about the distinct FF-A v1.1 and v1.2 RX/TX header
> layouts so we can propagate the 128-bit UUIDs introduced in v1.2.
>
> VM-to-VM SEND2 calls now build the larger v1.2 header, zeroing the UUID
> fields for v1.1 senders, and the dispatcher validates messages using
> the v1.1 header layout to keep legacy guests working.
>
> While there, make the code more robust by checking that the send is not
> trying to send a message to himself.
>
> Signed-off-by: Bertrand Marquis <[email protected]>
> ---
> Changes in v1:
> - Mention self send check in commit message
> - check header size depending on sender FF-A version and make sure 1.2
>   has enough space for 1.2 header
> - Simplify the code by setting uuid field of the header to Nil-UUID when
>   testing the caller version and remove the need to pass the context to
>   the send2_vm function
> - Use ACCESS_ONCE when reading sender ffa version
> ---
>  xen/arch/arm/tee/ffa_msg.c | 58 ++++++++++++++++++++++++++++++--------
>  1 file changed, 47 insertions(+), 11 deletions(-)

Looks good
Reviewed-by: Jens Wiklander <[email protected]>

Cheers,
Jens

>
> diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c
> index 5a4cb1bb8295..c3552a3ae36d 100644
> --- a/xen/arch/arm/tee/ffa_msg.c
> +++ b/xen/arch/arm/tee/ffa_msg.c
> @@ -13,7 +13,7 @@
>  #include "ffa_private.h"
>
>  /* Encoding of partition message in RX/TX buffer */
> -struct ffa_part_msg_rxtx {
> +struct ffa_part_msg_rxtx_1_1 {
>      uint32_t flags;
>      uint32_t reserved;
>      uint32_t msg_offset;
> @@ -21,6 +21,16 @@ struct ffa_part_msg_rxtx {
>      uint32_t msg_size;
>  };
>
> +struct ffa_part_msg_rxtx_1_2 {
> +    uint32_t flags;
> +    uint32_t reserved;
> +    uint32_t msg_offset;
> +    uint32_t send_recv_id;
> +    uint32_t msg_size;
> +    uint32_t reserved2;
> +    uint64_t uuid[2];
> +};
> +
>  static void ffa_finish_direct_req_run(struct cpu_user_regs *regs,
>                                        struct arm_smccc_1_2_regs *req)
>  {
> @@ -105,11 +115,11 @@ out:
>  }
>
>  static int32_t ffa_msg_send2_vm(uint16_t dst_id, const void *src_buf,
> -                                struct ffa_part_msg_rxtx *src_msg)
> +                                struct ffa_part_msg_rxtx_1_2 *src_msg)
>  {
>      struct domain *dst_d;
>      struct ffa_ctx *dst_ctx;
> -    struct ffa_part_msg_rxtx *dst_msg;
> +    struct ffa_part_msg_rxtx_1_2 *dst_msg;
>      void *rx_buf;
>      size_t rx_size;
>      int err;
> @@ -143,7 +153,7 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const 
> void *src_buf,
>          goto out_unlock;
>
>      /* we need to have enough space in the destination buffer */
> -    if ( (rx_size - sizeof(struct ffa_part_msg_rxtx)) < src_msg->msg_size )
> +    if ( (rx_size - sizeof(struct ffa_part_msg_rxtx_1_2)) < 
> src_msg->msg_size )
>      {
>          ret = FFA_RET_NO_MEMORY;
>          ffa_rx_release(dst_ctx);
> @@ -155,11 +165,14 @@ static int32_t ffa_msg_send2_vm(uint16_t dst_id, const 
> void *src_buf,
>      /* prepare destination header */
>      dst_msg->flags = 0;
>      dst_msg->reserved = 0;
> -    dst_msg->msg_offset = sizeof(struct ffa_part_msg_rxtx);
> +    dst_msg->msg_offset = sizeof(struct ffa_part_msg_rxtx_1_2);
>      dst_msg->send_recv_id = src_msg->send_recv_id;
>      dst_msg->msg_size = src_msg->msg_size;
> +    dst_msg->reserved2 = 0;
> +    dst_msg->uuid[0] = src_msg->uuid[0];
> +    dst_msg->uuid[1] = src_msg->uuid[1];
>
> -    memcpy(rx_buf + sizeof(struct ffa_part_msg_rxtx),
> +    memcpy(rx_buf + sizeof(struct ffa_part_msg_rxtx_1_2),
>             src_buf + src_msg->msg_offset, src_msg->msg_size);
>
>      /* receiver rx buffer will be released by the receiver*/
> @@ -178,11 +191,17 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs)
>      struct ffa_ctx *src_ctx = src_d->arch.tee;
>      const void *tx_buf;
>      size_t tx_size;
> -    struct ffa_part_msg_rxtx src_msg;
> +    /*
> +     * src_msg is interpreted as v1.2 header, but:
> +     * - for v1.1 guests, uuid[] is ignored and may contain payload bytes
> +     * - for v1.2 guests, uuid[] carries the FF-A v1.2 UUID fields
> +     */
> +    struct ffa_part_msg_rxtx_1_2 src_msg;
>      uint16_t dst_id, src_id;
>      int32_t ret;
>
> -    BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx) >= FFA_PAGE_SIZE);
> +    BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx_1_1) >= FFA_PAGE_SIZE);
> +    BUILD_BUG_ON(sizeof(struct ffa_part_msg_rxtx_1_2) >= FFA_PAGE_SIZE);
>
>      ret = ffa_tx_acquire(src_ctx, &tx_buf, &tx_size);
>      if ( ret != FFA_RET_OK )
> @@ -194,15 +213,32 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs)
>      src_id = src_msg.send_recv_id >> 16;
>      dst_id = src_msg.send_recv_id & GENMASK(15,0);
>
> -    if ( src_id != ffa_get_vm_id(src_d) )
> +    if ( src_id != ffa_get_vm_id(src_d) ||
> +         dst_id == ffa_get_vm_id(src_d) )
> +    {
> +        ret = FFA_RET_INVALID_PARAMETERS;
> +        goto out;
> +    }
> +
> +    if ( ACCESS_ONCE(src_ctx->guest_vers) < FFA_VERSION_1_2 )
> +    {
> +        if (src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx_1_1))
> +        {
> +            ret = FFA_RET_INVALID_PARAMETERS;
> +            goto out;
> +        }
> +        /* Set uuid to Nil UUID for v1.1 guests */
> +        src_msg.uuid[0] = 0;
> +        src_msg.uuid[1] = 0;
> +    }
> +    else if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx_1_2) )
>      {
>          ret = FFA_RET_INVALID_PARAMETERS;
>          goto out;
>      }
>
>      /* check source message fits in buffer */
> -    if ( src_msg.msg_offset < sizeof(struct ffa_part_msg_rxtx) ||
> -            src_msg.msg_size == 0 || src_msg.msg_offset > tx_size ||
> +    if ( src_msg.msg_size == 0 || src_msg.msg_offset > tx_size ||
>              src_msg.msg_size > (tx_size - src_msg.msg_offset) )
>      {
>          ret = FFA_RET_INVALID_PARAMETERS;
> --
> 2.51.2
>

Reply via email to