[PATCH] xen/arm: ffa: Harden SEND2 against invented loads

Bertrand Marquis <[email protected]>
Newsgroups gmane.comp.emulators.xen.devel
Message-ID <1b483ce633bfa7d304cb78458ce029370691f00c.1787055320.git.bertrand.marquis@arm.com>
Research into compiler-invented loads has flagged FFA_MSG_SEND2 as a
possible vulnerability.

ffa_handle_msg_send2() copies the message header from the guest-writable
TX buffer before validating and using its fields. A plain structure copy
does not prevent the compiler from re-deriving later field accesses from
the live TX mapping.

For VM-to-VM messages, msg_offset and msg_size are validated against the
source and destination buffers, then used to copy the payload. If a
sibling vCPU changes the header and the compiler reloads either field,
the checked and used values can differ. This can cause an out-of-bounds
read from the sender's TX buffer or an out-of-bounds write into the
receiver's RX buffer.

The cross-VM path is gated by CONFIG_FFA_VM_TO_VM, which is disabled by
default. The audit ranks the likelihood of such a reload as low, but the
C semantics do not guarantee that later accesses use the stack copy.

Add a compiler barrier immediately after copying the header so that
validation and use consume the same snapshot.

Link: https://github.com/xoreaxeaxeax/schrodingers-toctou/blob/main/observer-effect/audits/audit-xen-tee-mediator-RELEASE-4.21.1.md#tm-2--ff-a-txrx-buffers-ffa_shmc-ffa_msgc
Fixes: 98af565b1e61 ("xen/arm: ffa: Add indirect message between VM")
Signed-off-by: Bertrand Marquis <[email protected]>
---
 xen/arch/arm/tee/ffa_msg.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/xen/arch/arm/tee/ffa_msg.c b/xen/arch/arm/tee/ffa_msg.c
index 1eadc62870f2..39f561c8237f 100644
--- a/xen/arch/arm/tee/ffa_msg.c
+++ b/xen/arch/arm/tee/ffa_msg.c
@@ -257,6 +257,11 @@ int32_t ffa_handle_msg_send2(struct cpu_user_regs *regs)
 
     /* create a copy of the message header */
     memcpy(&src_msg, tx_buf, sizeof(src_msg));
+    /*
+     * Make sure that "tx_buf" which is shared with the guest isn't accessed
+     * again after this point.
+     */
+    barrier();
 
     src_id = src_msg.send_recv_id >> 16;
     dst_id = src_msg.send_recv_id & GENMASK(15,0);
-- 
2.53.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.