Skip to content

Commit d5d6489

Browse files
Snehal-Reddygregkh
authored andcommitted
KVM: arm64: Add memory length checks and remove inline in do_ffa_mem_xfer
commit f26a525 upstream. When we share memory through FF-A and the description of the buffers exceeds the size of the mapped buffer, the fragmentation API is used. The fragmentation API allows specifying chunks of descriptors in subsequent FF-A fragment calls and no upper limit has been established for this. The entire memory region transferred is identified by a handle which can be used to reclaim the transferred memory. To be able to reclaim the memory, the description of the buffers has to fit in the ffa_desc_buf. Add a bounds check on the FF-A sharing path to prevent the memory reclaim from failing. Also do_ffa_mem_xfer() does not need __always_inline, except for the BUILD_BUG_ON() aspect, which gets moved to a macro. [maz: fixed the BUILD_BUG_ON() breakage with LLVM, thanks to Wei-Lin Chang for the timely report] Fixes: 634d90c ("KVM: arm64: Handle FFA_MEM_LEND calls from the host") Cc: [email protected] Reviewed-by: Sebastian Ene <[email protected]> Signed-off-by: Snehal Koukuntla <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 0188ea5 commit d5d6489

File tree

1 file changed

+15
-6
lines changed
  • arch/arm64/kvm/hyp/nvhe

1 file changed

+15
-6
lines changed

arch/arm64/kvm/hyp/nvhe/ffa.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,9 +415,9 @@ static void do_ffa_mem_frag_tx(struct arm_smccc_res *res,
415415
return;
416416
}
417417

418-
static __always_inline void do_ffa_mem_xfer(const u64 func_id,
419-
struct arm_smccc_res *res,
420-
struct kvm_cpu_context *ctxt)
418+
static void __do_ffa_mem_xfer(const u64 func_id,
419+
struct arm_smccc_res *res,
420+
struct kvm_cpu_context *ctxt)
421421
{
422422
DECLARE_REG(u32, len, ctxt, 1);
423423
DECLARE_REG(u32, fraglen, ctxt, 2);
@@ -428,9 +428,6 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
428428
u32 offset, nr_ranges;
429429
int ret = 0;
430430

431-
BUILD_BUG_ON(func_id != FFA_FN64_MEM_SHARE &&
432-
func_id != FFA_FN64_MEM_LEND);
433-
434431
if (addr_mbz || npages_mbz || fraglen > len ||
435432
fraglen > KVM_FFA_MBOX_NR_PAGES * PAGE_SIZE) {
436433
ret = FFA_RET_INVALID_PARAMETERS;
@@ -449,6 +446,11 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
449446
goto out_unlock;
450447
}
451448

449+
if (len > ffa_desc_buf.len) {
450+
ret = FFA_RET_NO_MEMORY;
451+
goto out_unlock;
452+
}
453+
452454
buf = hyp_buffers.tx;
453455
memcpy(buf, host_buffers.tx, fraglen);
454456

@@ -498,6 +500,13 @@ static __always_inline void do_ffa_mem_xfer(const u64 func_id,
498500
goto out_unlock;
499501
}
500502

503+
#define do_ffa_mem_xfer(fid, res, ctxt) \
504+
do { \
505+
BUILD_BUG_ON((fid) != FFA_FN64_MEM_SHARE && \
506+
(fid) != FFA_FN64_MEM_LEND); \
507+
__do_ffa_mem_xfer((fid), (res), (ctxt)); \
508+
} while (0);
509+
501510
static void do_ffa_mem_reclaim(struct arm_smccc_res *res,
502511
struct kvm_cpu_context *ctxt)
503512
{

0 commit comments

Comments
 (0)