* [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone
@ 2026-06-29 9:35 Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 1/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone Sebastian Ene
` (6 more replies)
0 siblings, 7 replies; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Remove the FFA_NOTIFICATION* calls from the blocklist used by the pKVM
FF-A proxy. This restriction was preventing the use of asynchronous
signaling mechanisms defined by the Arm FF-A specification to
communicate with the secure services.
While these calls are markes as optional, there is no reason why the
hypervisor proxy would block them because:
1. Host is the Sole Non-Secure Endpoint: The Host operates as the
only Non-Secure VM ID (VM ID 0) recognized by the Secure World.
Because all forwarded notifications are inherently attributed to
the Host by the SPMC, there is no risk of VM ID spoofing
originating from the Normal World.
2. No Memory Pointers or Addresses: The FFA_NOTIFICATION_* ABIs
operate strictly via register-based parameters, passing only
VM IDs, VCPU IDs, flags, and bitmaps. Because these calls do
not contain memory addresses, offsets, or pointers, forwarding
them doesn't pose a risk of memory-based confused deputy attack
(e.g., tricking the SPMC into overwriting protected memory).
While the pKVM proxy behaves as a relayer, it doesn't currently have its
own FF-A ID(only the host has the ID 0). The behavior of the setup
flow is covered by the spec in the: '10.9 Notification support without
a Hypervisor'.
---
Changes in v7:
- rebased on 7.2-rc1
- collected the Ack from Will
- check for major version as well when doing the SBZ/MBZ enforcement
Changes in v6:
- applied Will's feedback and re-ordered the patch series so that we
apply the MBZ enforcement at the end of the series
- update ffa_check_unused_args_sbz so that we take into account the FF-A
version because the spec changed the list of unused parameter registers
for 64-bit SMCs from v1.1 to v1.2
Changes in v5:
- handle 32-bit smc variants correctly when doing the MBZ enforcement
- add check for FFA_FEATURES
- handle missing FFA_FN64_NOTIFICATION_INFO_GET
- collected the Review tags from Vincent, thank you
Changes in v4:
- previous series(v3) had serious issues with the patch number and it
appeared like it used a mixed bag from v2 as well. Resend this to
restore the correct order of the patches.
- fix strict check in ffa_check_unused_args_sbz and make it "<= 17"
- check the receiver endpoint Id in
FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND instead of the sender
- use hyp_smccc_1_2_smc all along
- check the receiver endpoit Id when doing FFA_NOTIFICATION_GET
Changes in v3:
- applied Will's suggestion to use the introduced method
ffa_check_unused_args_sbz for existing calls and added a new
patch in the beggining of the series to do this.
- merged the handling of
FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY into
one patch as Vincent suggested and create one handler for both.
Changes in v2:
- enforce the MBZ/SBZ fields
- split the calls into separate patches
- rebase on 7.1-rc7
Link to v5:
https://lore.kernel.org/all/20260623115354.632361-1-sebastianene@google.com/
Link to v4:
https://lore.kernel.org/all/20260616154149.2763214-1-sebastianene@google.com/
Link to v3:
https://lore.kernel.org/all/20260616105417.2578670-1-sebastianene@google.com/
Link to v2:
https://lore.kernel.org/all/20260608165549.1479409-1-sebastianene@google.com/
Link to v1:
https://lore.kernel.org/all/20260501114447.2389222-2-sebastianene@google.com/
Sebastian Ene (7):
KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone
KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler
KVM: arm64: Support FFA_NOTIFICATION_UNBIND in host handler
KVM: arm64: Support FFA_NOTIFICATION_SET in host handler
KVM: arm64: Support FFA_NOTIFICATION_GET in host handler
KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
KVM: arm64: Enforce strict SBZ checks in the FF-A proxy
arch/arm64/kvm/hyp/nvhe/ffa.c | 220 ++++++++++++++++++++++++++++++++--
1 file changed, 212 insertions(+), 8 deletions(-)
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v7 1/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 2/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler Sebastian Ene
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Allow FF-A notification bitmap messages to be forwarded to
Trustzone from the host kernel driver and enforce the host vmid
check.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 1af722771178..ecc13b795f2c 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -676,8 +676,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
/* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_BITMAP_CREATE:
- case FFA_NOTIFICATION_BITMAP_DESTROY:
case FFA_NOTIFICATION_BIND:
case FFA_NOTIFICATION_UNBIND:
case FFA_NOTIFICATION_SET:
@@ -862,6 +860,21 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
hyp_spin_unlock(&host_buffers.lock);
}
+static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, vmid, ctxt, 1);
+ struct arm_smccc_1_2_regs *args;
+
+ if (vmid != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -920,6 +933,10 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_PARTITION_INFO_GET:
do_ffa_part_get(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_BITMAP_CREATE:
+ case FFA_NOTIFICATION_BITMAP_DESTROY:
+ do_ffa_notif_bitmap(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 2/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 1/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND " Sebastian Ene
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Verify the arguments of the FF-A notification bind call and forward the
message to Trustzone.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 27 ++++++++++++++++++++++++++-
1 file changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index ecc13b795f2c..331d9d0d8287 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -42,6 +42,8 @@
*/
#define HOST_FFA_ID 0
+#define FFA_NOTIF_RECEIVER_ENDP_MASK GENMASK(15, 0)
+
/*
* A buffer to hold the maximum descriptor size we can see from the host,
* which is required when the SPMD returns a fragmented FFA_MEM_RETRIEVE_RESP
@@ -676,7 +678,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
/* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_BIND:
case FFA_NOTIFICATION_UNBIND:
case FFA_NOTIFICATION_SET:
case FFA_NOTIFICATION_GET:
@@ -875,6 +876,27 @@ static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
hyp_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, endp_id, ctxt, 1);
+ DECLARE_REG(u32, flags, ctxt, 2);
+ struct arm_smccc_1_2_regs *args;
+
+ if (FIELD_GET(FFA_NOTIF_RECEIVER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (flags > 1) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -937,6 +959,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_BITMAP_DESTROY:
do_ffa_notif_bitmap(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_BIND:
+ do_ffa_notif_bind(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND in host handler
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 1/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 2/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 10:16 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET " Sebastian Ene
` (3 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Verify the arguments of the FF-A notification unbind call and forward
the message to Trustzone.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 331d9d0d8287..d52d7c4d5e7f 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -678,7 +678,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
/* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_UNBIND:
case FFA_NOTIFICATION_SET:
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
@@ -897,6 +896,27 @@ static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
hyp_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, endp_id, ctxt, 1);
+ DECLARE_REG(u32, reserved, ctxt, 2);
+ struct arm_smccc_1_2_regs *args;
+
+ if (reserved) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (FIELD_GET(FFA_NOTIF_RECEIVER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -962,6 +982,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_BIND:
do_ffa_notif_bind(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_UNBIND:
+ do_ffa_notif_unbind(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET in host handler
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
` (2 preceding siblings ...)
2026-06-29 9:35 ` [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND " Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 10:25 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 5/7] KVM: arm64: Support FFA_NOTIFICATION_GET " Sebastian Ene
` (2 subsequent siblings)
6 siblings, 1 reply; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Allow FF-A notification SET messages to be proxied from the pKVM
hypervisor to Trustzone and verify the arguments.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index d52d7c4d5e7f..2bb16aa414f9 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -43,6 +43,7 @@
#define HOST_FFA_ID 0
#define FFA_NOTIF_RECEIVER_ENDP_MASK GENMASK(15, 0)
+#define FFA_NOTIF_SENDER_ENDP_MASK GENMASK(31, 16)
/*
* A buffer to hold the maximum descriptor size we can see from the host,
@@ -678,7 +679,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
/* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_SET:
case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
/* Optional interfaces added in FF-A 1.2 */
@@ -917,6 +917,27 @@ static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
hyp_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_set(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, endp_id, ctxt, 1);
+ DECLARE_REG(u32, flags, ctxt, 2);
+ struct arm_smccc_1_2_regs *args;
+
+ if (FIELD_GET(FFA_NOTIF_SENDER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (flags & GENMASK(15, 2)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -985,6 +1006,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_UNBIND:
do_ffa_notif_unbind(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_SET:
+ do_ffa_notif_set(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 5/7] KVM: arm64: Support FFA_NOTIFICATION_GET in host handler
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
` (3 preceding siblings ...)
2026-06-29 9:35 ` [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET " Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET " Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy Sebastian Ene
6 siblings, 0 replies; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Allow FF-A notification GET messages to be proxied from the pKVM
hypervisor to Trustzone and verify the arguments sent from the host
driver.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 2bb16aa414f9..c22fe4514741 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -679,7 +679,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
/* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_GET:
case FFA_NOTIFICATION_INFO_GET:
/* Optional interfaces added in FF-A 1.2 */
case FFA_MSG_SEND_DIRECT_REQ2: /* Optional per 7.5.1 */
@@ -938,6 +937,27 @@ static void do_ffa_notif_set(struct arm_smccc_1_2_regs *res,
hyp_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_get(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ DECLARE_REG(u32, endp_id, ctxt, 1);
+ DECLARE_REG(u32, flags, ctxt, 2);
+ struct arm_smccc_1_2_regs *args;
+
+ if (FIELD_GET(FFA_NOTIF_RECEIVER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ if (flags & GENMASK(31, 4)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -1009,6 +1029,9 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_SET:
do_ffa_notif_set(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_GET:
+ do_ffa_notif_get(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
` (4 preceding siblings ...)
2026-06-29 9:35 ` [PATCH v7 5/7] KVM: arm64: Support FFA_NOTIFICATION_GET " Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 12:46 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy Sebastian Ene
6 siblings, 1 reply; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Allow the host to send FF-A notification queries to Trustzone and proxy
these messages from pKVM.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index c22fe4514741..712811e89435 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -678,8 +678,6 @@ static bool ffa_call_supported(u64 func_id)
case FFA_RXTX_MAP:
case FFA_MEM_DONATE:
case FFA_MEM_RETRIEVE_REQ:
- /* Optional notification interfaces added in FF-A 1.1 */
- case FFA_NOTIFICATION_INFO_GET:
/* Optional interfaces added in FF-A 1.2 */
case FFA_MSG_SEND_DIRECT_REQ2: /* Optional per 7.5.1 */
case FFA_MSG_SEND_DIRECT_RESP2: /* Optional per 7.5.1 */
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
` (5 preceding siblings ...)
2026-06-29 9:35 ` [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET " Sebastian Ene
@ 2026-06-29 9:35 ` Sebastian Ene
2026-06-29 12:58 ` sashiko-bot
6 siblings, 1 reply; 12+ messages in thread
From: Sebastian Ene @ 2026-06-29 9:35 UTC (permalink / raw)
To: catalin.marinas, maz, oupton, will
Cc: joey.gouly, korneld, kvmarm, linux-arm-kernel, linux-kernel,
android-kvm, mrigendra.chaubey, perlarsen, sebastianene,
suzuki.poulose, vdonnefort, yuzenghui
Introduce a helper method ffa_check_unused_args_sbz to enforce strict
arguments checking when the hypervisor acts as a relayer between the
host and Trustzone.
Signed-off-by: Sebastian Ene <sebastianene@google.com>
Reviewed-by: Vincent Donnefort <vdonnefort@google.com>
Acked-by: Will Deacon <will@kernel.org>
---
arch/arm64/kvm/hyp/nvhe/ffa.c | 96 ++++++++++++++++++++++++++++++++++-
1 file changed, 95 insertions(+), 1 deletion(-)
diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
index 712811e89435..334f8a28d942 100644
--- a/arch/arm64/kvm/hyp/nvhe/ffa.c
+++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
@@ -74,6 +74,21 @@ static u32 hyp_ffa_version;
static bool has_version_negotiated;
static hyp_spinlock_t version_lock;
+static bool ffa_check_unused_args_sbz(struct kvm_cpu_context *ctxt, int first_reg)
+{
+ DECLARE_REG(u32, func_id, ctxt, 0);
+ int reg, end_reg = 7;
+
+ if (hyp_ffa_version >= FFA_VERSION_1_2 && ARM_SMCCC_IS_64(func_id))
+ end_reg = 17;
+ for (reg = first_reg; reg <= end_reg; reg++) {
+ if (cpu_reg(ctxt, reg))
+ return true;
+ }
+
+ return false;
+}
+
static void ffa_to_smccc_error(struct arm_smccc_1_2_regs *res, u64 ffa_errno)
{
*res = (struct arm_smccc_1_2_regs) {
@@ -242,6 +257,11 @@ static void do_ffa_rxtx_map(struct arm_smccc_1_2_regs *res,
int ret = 0;
void *rx_virt, *tx_virt;
+ if (ffa_check_unused_args_sbz(ctxt, 4)) {
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out;
+ }
+
if (npages != (KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) / FFA_PAGE_SIZE) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out;
@@ -318,6 +338,11 @@ static void do_ffa_rxtx_unmap(struct arm_smccc_1_2_regs *res,
DECLARE_REG(u32, id, ctxt, 1);
int ret = 0;
+ if (ffa_check_unused_args_sbz(ctxt, 2)) {
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out;
+ }
+
if (id != HOST_FFA_ID) {
ret = FFA_RET_INVALID_PARAMETERS;
goto out;
@@ -424,6 +449,11 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_1_2_regs *res,
int ret = FFA_RET_INVALID_PARAMETERS;
u32 nr_ranges;
+ if (ffa_check_unused_args_sbz(ctxt, 5)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
if (fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE)
goto out;
@@ -485,6 +515,11 @@ static void __do_ffa_mem_xfer(const u64 func_id,
u32 offset, nr_ranges, checked_offset;
int ret = 0;
+ if (ffa_check_unused_args_sbz(ctxt, 5)) {
+ ret = FFA_RET_INVALID_PARAMETERS;
+ goto out;
+ }
+
if (addr_mbz || npages_mbz || fraglen > len ||
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
ret = FFA_RET_INVALID_PARAMETERS;
@@ -584,6 +619,11 @@ static void do_ffa_mem_reclaim(struct arm_smccc_1_2_regs *res,
int ret = 0;
u64 handle;
+ if (ffa_check_unused_args_sbz(ctxt, 4)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
handle = PACK_HANDLE(handle_lo, handle_hi);
hyp_spin_lock(&host_buffers.lock);
@@ -764,6 +804,11 @@ static void do_ffa_version(struct arm_smccc_1_2_regs *res,
{
DECLARE_REG(u32, ffa_req_version, ctxt, 1);
+ if (ffa_check_unused_args_sbz(ctxt, 2)) {
+ res->a0 = FFA_RET_NOT_SUPPORTED;
+ return;
+ }
+
if (FFA_MAJOR_VERSION(ffa_req_version) != 1) {
res->a0 = FFA_RET_NOT_SUPPORTED;
return;
@@ -813,6 +858,11 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
DECLARE_REG(u32, flags, ctxt, 5);
u32 count, partition_sz, copy_sz;
+ if (ffa_check_unused_args_sbz(ctxt, 6)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
hyp_spin_lock(&host_buffers.lock);
if (!host_buffers.rx) {
ffa_to_smccc_res(res, FFA_RET_BUSY);
@@ -860,9 +910,15 @@ static void do_ffa_part_get(struct arm_smccc_1_2_regs *res,
static void do_ffa_notif_bitmap(struct arm_smccc_1_2_regs *res,
struct kvm_cpu_context *ctxt)
{
+ DECLARE_REG(u32, func_id, ctxt, 0);
DECLARE_REG(u32, vmid, ctxt, 1);
struct arm_smccc_1_2_regs *args;
+ if (ffa_check_unused_args_sbz(ctxt, func_id == FFA_NOTIFICATION_BITMAP_CREATE ? 3 : 2)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
if (vmid != HOST_FFA_ID) {
ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
return;
@@ -879,6 +935,11 @@ static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
DECLARE_REG(u32, flags, ctxt, 2);
struct arm_smccc_1_2_regs *args;
+ if (ffa_check_unused_args_sbz(ctxt, 5)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
if (FIELD_GET(FFA_NOTIF_RECEIVER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
return;
@@ -900,7 +961,7 @@ static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
DECLARE_REG(u32, reserved, ctxt, 2);
struct arm_smccc_1_2_regs *args;
- if (reserved) {
+ if (ffa_check_unused_args_sbz(ctxt, 5) || reserved) {
ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
return;
}
@@ -926,6 +987,11 @@ static void do_ffa_notif_set(struct arm_smccc_1_2_regs *res,
return;
}
+ if (ffa_check_unused_args_sbz(ctxt, 5)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
if (flags & GENMASK(15, 2)) {
ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
return;
@@ -947,6 +1013,11 @@ static void do_ffa_notif_get(struct arm_smccc_1_2_regs *res,
return;
}
+ if (ffa_check_unused_args_sbz(ctxt, 3)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
if (flags & GENMASK(31, 4)) {
ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
return;
@@ -956,6 +1027,20 @@ static void do_ffa_notif_get(struct arm_smccc_1_2_regs *res,
hyp_smccc_1_2_smc(args, res);
}
+static void do_ffa_notif_info_get(struct arm_smccc_1_2_regs *res,
+ struct kvm_cpu_context *ctxt)
+{
+ struct arm_smccc_1_2_regs *args;
+
+ if (ffa_check_unused_args_sbz(ctxt, 1)) {
+ ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
+ return;
+ }
+
+ args = (void *)&ctxt->regs.regs[0];
+ hyp_smccc_1_2_smc(args, res);
+}
+
bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
{
struct arm_smccc_1_2_regs res;
@@ -984,6 +1069,11 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
switch (func_id) {
case FFA_FEATURES:
+ if (ffa_check_unused_args_sbz(host_ctxt, 3)) {
+ ffa_to_smccc_res(&res, FFA_RET_INVALID_PARAMETERS);
+ goto out_handled;
+ }
+
if (!do_ffa_features(&res, host_ctxt))
return false;
goto out_handled;
@@ -1030,6 +1120,10 @@ bool kvm_host_ffa_handler(struct kvm_cpu_context *host_ctxt, u32 func_id)
case FFA_NOTIFICATION_GET:
do_ffa_notif_get(&res, host_ctxt);
goto out_handled;
+ case FFA_NOTIFICATION_INFO_GET:
+ case FFA_FN64_NOTIFICATION_INFO_GET:
+ do_ffa_notif_info_get(&res, host_ctxt);
+ goto out_handled;
}
if (ffa_call_supported(func_id))
--
2.55.0.rc0.799.gd6f94ed593-goog
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND in host handler
2026-06-29 9:35 ` [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND " Sebastian Ene
@ 2026-06-29 10:16 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-29 10:16 UTC (permalink / raw)
To: Sebastian Ene; +Cc: Oliver Upton, Marc Zyngier, kvmarm
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] The FFA_NOTIFICATION_UNBIND handler incorrectly treats the W2 parameter as a reserved field and forces it to be zero, which violates the FF-A specification and breaks valid unbind operations.
--
commit 607a657720d57d669adb319d0385db08fa611fcc
Author: Sebastian Ene <sebastianene@google.com>
KVM: arm64: Support FFA_NOTIFICATION_UNBIND in host handler
This commit adds support for the FFA_NOTIFICATION_UNBIND host handler by
verifying the arguments and forwarding the message to TrustZone. It extracts
the endpoint ID and verifies that the correct host FF-A ID is used before
allowing the unbind operation to proceed.
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
[ ... ]
> @@ -897,6 +896,27 @@ static void do_ffa_notif_bind(struct arm_smccc_1_2_regs *res,
> hyp_smccc_1_2_smc(args, res);
> }
>
> +static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + DECLARE_REG(u32, endp_id, ctxt, 1);
> + DECLARE_REG(u32, reserved, ctxt, 2);
> + struct arm_smccc_1_2_regs *args;
> +
> + if (reserved) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
[Severity: High]
Does this incorrectly reject valid unbind operations? The FF-A specification
defines W2 as the Notification ID(s) Low bitmap for unbind requests.
By declaring W2 as reserved and forcing it to zero, it looks like this handler
prevents the host from unbinding any notifications that use the lower 32 bits
of the Notification ID bitmap.
Additionally, should there be an ffa_check_unused_args_sbz() call here to
verify the remaining unused registers are zeroed out, similar to the other
handlers?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629093558.2425257-1-sebastianene@google.com?part=3
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET in host handler
2026-06-29 9:35 ` [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET " Sebastian Ene
@ 2026-06-29 10:25 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-29 10:25 UTC (permalink / raw)
To: Sebastian Ene; +Cc: Marc Zyngier, kvmarm, Oliver Upton
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] Incomplete validation of MBZ bits in the `FFA_NOTIFICATION_SET` flags parameter.
--
commit 143dce86ae3c0640e01881b137e64cf1efebff28
Author: Sebastian Ene <sebastianene@google.com>
KVM: arm64: Support FFA_NOTIFICATION_SET in host handler
This commit allows FF-A notification SET messages to be proxied from the
pKVM hypervisor to Trustzone by validating the endpoint ID and flags arguments
before forwarding the hypercall.
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index d52d7c4d5e7f5..2bb16aa414f9f 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
[ ... ]
> @@ -917,6 +917,27 @@ static void do_ffa_notif_unbind(struct arm_smccc_1_2_regs *res,
> hyp_smccc_1_2_smc(args, res);
> }
>
> +static void do_ffa_notif_set(struct arm_smccc_1_2_regs *res,
> + struct kvm_cpu_context *ctxt)
> +{
> + DECLARE_REG(u32, endp_id, ctxt, 1);
> + DECLARE_REG(u32, flags, ctxt, 2);
> + struct arm_smccc_1_2_regs *args;
> +
> + if (FIELD_GET(FFA_NOTIF_SENDER_ENDP_MASK, endp_id) != HOST_FFA_ID) {
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + if (flags & GENMASK(15, 2)) {
[Severity: Medium]
Does this missing validation allow the host to pass arbitrary data in the
upper bits of the flags parameter to EL3?
In do_ffa_notif_set(), the check masks and verifies only bits 15:2. However,
the FF-A specification defines bits 31:16 as Must Be Zero (MBZ) as well.
This seems to introduce a regression where pKVM does not completely sanitize
host inputs before forwarding them to TrustZone, potentially exposing EL3
to unauthorized use of future extensions.
> + ffa_to_smccc_res(res, FFA_RET_INVALID_PARAMETERS);
> + return;
> + }
> +
> + args = (void *)&ctxt->regs.regs[0];
> + hyp_smccc_1_2_smc(args, res);
> +}
> +
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629093558.2425257-1-sebastianene@google.com?part=4
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
2026-06-29 9:35 ` [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET " Sebastian Ene
@ 2026-06-29 12:46 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-29 12:46 UTC (permalink / raw)
To: Sebastian Ene; +Cc: Marc Zyngier, kvmarm, Oliver Upton
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Critical] Passing through FFA_NOTIFICATION_INFO_GET without RX buffer proxying or locking causes memory corruption and DoS.
Pre-existing issues:
- [High] Missing masking of unsupported optional FF-A 1.1/1.2 interfaces (e.g., FFA_MSG_SEND2) leads to hypervisor information leaks.
--
commit a13e0f442f3327dcf7e9cad61d255528a3a9dd89
Author: Sebastian Ene <sebastianene@google.com>
KVM: arm64: Support FFA_NOTIFICATION_INFO_GET in host handler
This patch allows the host to send FF-A notification queries to Trustzone and
proxy these messages from pKVM.
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -678,8 +678,6 @@ static bool ffa_call_supported(u64 func_id)
> case FFA_RXTX_MAP:
> case FFA_MEM_DONATE:
> case FFA_MEM_RETRIEVE_REQ:
> - /* Optional notification interfaces added in FF-A 1.1 */
> - case FFA_NOTIFICATION_INFO_GET:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Severity: Critical]
Does removing this from the block list allow the call to pass directly
to EL3 without acquiring host_buffers.lock?
Under the FF-A 1.1 specification, if the endpoints list exceeds register
capacity, EL3 writes it to the caller's (EL2's) RX buffer (hyp_buffers.rx).
If this happens concurrently with do_ffa_mem_reclaim() running on another CPU,
could this un-locked write corrupt the buffer during parsing?
Also, since EL2 does not intercept this to proxy the data or issue an
FFA_RX_RELEASE, will hyp_buffers.rx be left permanently marked 'Full' by EL3,
causing subsequent hypercalls requiring the RX buffer to fail?
[Severity: High]
This is a pre-existing issue, but are we missing masking for other optional
FF-A 1.1/1.2 interfaces like FFA_MSG_SEND2, FFA_RX_ACQUIRE, and
FFA_MEM_PERM_GET here in ffa_call_supported()?
If FFA_MSG_SEND2 passes through to EL3, EL3 will read the message payload
from EL2's TX buffer (hyp_buffers.tx).
Since EL2 does not proxy this call or populate the TX buffer with the host's
data, could EL3 end up sending uninitialized or stale hypervisor memory
(such as previous memory sharing descriptors) to the destination partition?
> /* Optional interfaces added in FF-A 1.2 */
> case FFA_MSG_SEND_DIRECT_REQ2: /* Optional per 7.5.1 */
> case FFA_MSG_SEND_DIRECT_RESP2: /* Optional per 7.5.1 */
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629093558.2425257-1-sebastianene@google.com?part=6
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy
2026-06-29 9:35 ` [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy Sebastian Ene
@ 2026-06-29 12:58 ` sashiko-bot
0 siblings, 0 replies; 12+ messages in thread
From: sashiko-bot @ 2026-06-29 12:58 UTC (permalink / raw)
To: Sebastian Ene; +Cc: Marc Zyngier, kvmarm, Oliver Upton
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] Lockless read of `hyp_ffa_version` in `ffa_check_unused_args_sbz()` races with concurrent writes.
Pre-existing issues:
- [High] Uninitialized fields in the `res` structure leak EL2 stack memory to the host during FF-A version negotiation.
--
commit a19572356269d847d64eebb97bb025807ca073f2
Author: Sebastian Ene <sebastianene@google.com>
KVM: arm64: Enforce strict SBZ checks in the FF-A proxy
This patch introduces a helper function to enforce strict argument checking
when the hypervisor acts as a relayer between the host and Trustzone. It
adds calls to this new helper across various FF-A hypercall handlers to
ensure unused arguments are zeroed.
> diff --git a/arch/arm64/kvm/hyp/nvhe/ffa.c b/arch/arm64/kvm/hyp/nvhe/ffa.c
> index 712811e894352..334f8a28d942d 100644
> --- a/arch/arm64/kvm/hyp/nvhe/ffa.c
> +++ b/arch/arm64/kvm/hyp/nvhe/ffa.c
> @@ -74,6 +74,21 @@ static u32 hyp_ffa_version;
> static bool has_version_negotiated;
> static hyp_spinlock_t version_lock;
>
> +static bool ffa_check_unused_args_sbz(struct kvm_cpu_context *ctxt, int first_reg)
> +{
> + DECLARE_REG(u32, func_id, ctxt, 0);
> + int reg, end_reg = 7;
> +
> + if (hyp_ffa_version >= FFA_VERSION_1_2 && ARM_SMCCC_IS_64(func_id))
[Severity: Medium]
Can this lockless read of hyp_ffa_version cause a data race?
During host initialization, multiple CPUs could issue the FFA_VERSION
hypercall concurrently. If CPU A acquires version_lock in do_ffa_version()
and writes to hyp_ffa_version, CPU B entering do_ffa_version() and calling
ffa_check_unused_args_sbz() will evaluate this condition.
Since logical AND evaluates left-to-right, CPU B could locklessly read
hyp_ffa_version while CPU A is writing it. Swapping the conditions to check
ARM_SMCCC_IS_64(func_id) first would short-circuit the evaluation for
FFA_VERSION (which is an SMC32 call) and avoid the unprotected read entirely.
> + end_reg = 17;
> + for (reg = first_reg; reg <= end_reg; reg++) {
> + if (cpu_reg(ctxt, reg))
> + return true;
> + }
> +
> + return false;
> +}
[ ... ]
> @@ -764,6 +804,11 @@ static void do_ffa_version(struct arm_smccc_1_2_regs *res,
> {
> DECLARE_REG(u32, ffa_req_version, ctxt, 1);
>
> + if (ffa_check_unused_args_sbz(ctxt, 2)) {
> + res->a0 = FFA_RET_NOT_SUPPORTED;
> + return;
> + }
[Severity: High]
This is a pre-existing issue, but does this code leak uninitialized EL2
stack memory to the host?
In kvm_host_ffa_handler(), an uninitialized struct arm_smccc_1_2_regs res
is declared on the stack. When do_ffa_version() is called (both on this
newly added failure path and the existing paths), it only manually assigns
res->a0 before returning.
Back in kvm_host_ffa_handler(), ffa_set_retval(host_ctxt, &res) then
blindly copies the entire structure into the host context, which exposes
the uninitialized a1-a17 fields to the untrusted host.
> +
> if (FFA_MAJOR_VERSION(ffa_req_version) != 1) {
> res->a0 = FFA_RET_NOT_SUPPORTED;
> return;
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260629093558.2425257-1-sebastianene@google.com?part=7
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-29 12:58 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-29 9:35 [PATCH v7 0/7] KVM: arm64: Forward FFA_NOTIFICATION* calls to TrustZone Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 1/7] KVM: arm64: Forward FFA_NOTIFICATION_BITMAP calls to Trustzone Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 2/7] KVM: arm64: Support FFA_NOTIFICATION_BIND in host handler Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 3/7] KVM: arm64: Support FFA_NOTIFICATION_UNBIND " Sebastian Ene
2026-06-29 10:16 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 4/7] KVM: arm64: Support FFA_NOTIFICATION_SET " Sebastian Ene
2026-06-29 10:25 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 5/7] KVM: arm64: Support FFA_NOTIFICATION_GET " Sebastian Ene
2026-06-29 9:35 ` [PATCH v7 6/7] KVM: arm64: Support FFA_NOTIFICATION_INFO_GET " Sebastian Ene
2026-06-29 12:46 ` sashiko-bot
2026-06-29 9:35 ` [PATCH v7 7/7] KVM: arm64: Enforce strict SBZ checks in the FF-A proxy Sebastian Ene
2026-06-29 12:58 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.