fix(ff-a): prevent mem-share/lend from SP to NS-endpoint

Only FFA_MEM_DONATE_32 is permitted from SP to NS-endpoint.

Signed-off-by: Maksims Svecovs <maksims.svecovs@arm.com>
Change-Id: I3fe611b5c239e896af421ed430770d6c25af2096
diff --git a/src/api.c b/src/api.c
index a507e34..ac3a741 100644
--- a/src/api.c
+++ b/src/api.c
@@ -2432,6 +2432,11 @@
 		goto out;
 	}
 
+	if (!plat_ffa_is_memory_send_valid(to->id, share_func)) {
+		ret = ffa_error(FFA_DENIED);
+		goto out;
+	}
+
 	if (to->id == HF_TEE_VM_ID) {
 		/*
 		 * The 'to' VM lock is only needed in the case that it is the
diff --git a/src/arch/aarch64/plat/ffa/absent.c b/src/arch/aarch64/plat/ffa/absent.c
index c6a7d4c..17eec1b 100644
--- a/src/arch/aarch64/plat/ffa/absent.c
+++ b/src/arch/aarch64/plat/ffa/absent.c
@@ -42,6 +42,18 @@
 }
 
 /**
+ * Check validity of the FF-A memory send function attempt.
+ */
+bool plat_ffa_is_memory_send_valid(ffa_vm_id_t receiver_vm_id,
+				   uint32_t share_func)
+{
+	(void)receiver_vm_id;
+	(void)share_func;
+
+	return false;
+}
+
+/**
  * Check validity of a FF-A direct message request.
  */
 bool plat_ffa_is_direct_request_valid(struct vcpu *current,
diff --git a/src/arch/aarch64/plat/ffa/hypervisor.c b/src/arch/aarch64/plat/ffa/hypervisor.c
index b7361fb..a53375b 100644
--- a/src/arch/aarch64/plat/ffa/hypervisor.c
+++ b/src/arch/aarch64/plat/ffa/hypervisor.c
@@ -140,6 +140,23 @@
 }
 
 /**
+ * Check validity of the FF-A memory send function attempt.
+ */
+bool plat_ffa_is_memory_send_valid(ffa_vm_id_t receiver_vm_id,
+				   uint32_t share_func)
+{
+	/*
+	 * Currently memory interfaces are not forwarded from hypervisor to
+	 * SPMC. However, in absence of SPMC this function should allow
+	 * NS-endpoint to SP memory send in order for trusty tests to work.
+	 */
+
+	(void)share_func;
+	(void)receiver_vm_id;
+	return true;
+}
+
+/**
  * Check validity of a FF-A direct message request.
  */
 bool plat_ffa_is_direct_request_valid(struct vcpu *current,
diff --git a/src/arch/aarch64/plat/ffa/spmc.c b/src/arch/aarch64/plat/ffa/spmc.c
index b24ed8a..203b71e 100644
--- a/src/arch/aarch64/plat/ffa/spmc.c
+++ b/src/arch/aarch64/plat/ffa/spmc.c
@@ -168,6 +168,42 @@
 }
 
 /**
+ * Check validity of the FF-A memory send function attempt.
+ */
+bool plat_ffa_is_memory_send_valid(ffa_vm_id_t receiver_vm_id,
+				   uint32_t share_func)
+{
+	bool result = false;
+
+	/*
+	 * Currently SP to NS-endpoint memory donation is limited:
+	 * In it's current implementation SPMC is not aware of the memory type
+	 * being donated and can not ensure that the memory type is marked as
+	 * non-secure when SP is donating to NS-endpoint.
+	 */
+	switch (share_func) {
+	case FFA_MEM_DONATE_32:
+		result = true;
+		break;
+	case FFA_MEM_LEND_32:
+	case FFA_MEM_SHARE_32:
+		/* SP to VM not allowed, VM to VM should not end up here */
+		result = vm_id_is_current_world(receiver_vm_id);
+		if (!result) {
+			dlog_verbose(
+				"SP to NS-endpoint memory sharing/lending is "
+				"not "
+				"permitted.\n");
+		}
+		break;
+	default:
+		result = false;
+	}
+
+	return result;
+}
+
+/**
  * Check validity of a FF-A direct message request.
  */
 bool plat_ffa_is_direct_request_valid(struct vcpu *current,
diff --git a/src/arch/fake/hypervisor/ffa.c b/src/arch/fake/hypervisor/ffa.c
index 91bebd4..236fb16 100644
--- a/src/arch/fake/hypervisor/ffa.c
+++ b/src/arch/fake/hypervisor/ffa.c
@@ -29,6 +29,15 @@
 {
 }
 
+bool plat_ffa_is_memory_send_valid(ffa_vm_id_t receiver_vm_id,
+				   uint32_t share_func)
+{
+	(void)receiver_vm_id;
+	(void)share_func;
+
+	return true;
+}
+
 bool plat_ffa_is_direct_request_valid(struct vcpu *current,
 				      ffa_vm_id_t sender_vm_id,
 				      ffa_vm_id_t receiver_vm_id)