fix(memory share): check that lengths are 16-byte aligned

The fragment and total length must be 16-byte aligned.  This ensures
that size of the constituents array is a multiple of sizeof(struct
ffa_memory_region_constituent) and that there will be no alignment
problems when dereferencing pointers.

Change-Id: I4e4ce76a1ad897d01e2fab1dad5e4e43dbd19832
Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
diff --git a/src/ffa_memory.c b/src/ffa_memory.c
index a7d94ec..85e8d62 100644
--- a/src/ffa_memory.c
+++ b/src/ffa_memory.c
@@ -1211,6 +1211,19 @@
 		return ffa_error(FFA_INVALID_PARAMETERS);
 	}
 
+	static_assert(sizeof(struct ffa_memory_region_constituent) == 16,
+		      "struct ffa_memory_region_constituent must be 16 bytes");
+	if (!is_aligned(fragment_length,
+			sizeof(struct ffa_memory_region_constituent)) ||
+	    !is_aligned(memory_share_length,
+			sizeof(struct ffa_memory_region_constituent))) {
+		dlog_verbose(
+			"Fragment length %u or total length %u"
+			" is not 16-byte aligned.\n",
+			fragment_length, memory_share_length);
+		return ffa_error(FFA_INVALID_PARAMETERS);
+	}
+
 	if (fragment_length > memory_share_length) {
 		dlog_verbose(
 			"Fragment length %u greater than total length %u.\n",
@@ -1657,6 +1670,16 @@
 	struct ffa_value ret;
 	struct ffa_memory_region *memory_region;
 
+	CHECK(is_aligned(fragment,
+			 alignof(struct ffa_memory_region_constituent)));
+	if (fragment_length % sizeof(struct ffa_memory_region_constituent) !=
+	    0) {
+		dlog_verbose("Fragment length %u misaligned.\n",
+			     fragment_length);
+		ret = ffa_error(FFA_INVALID_PARAMETERS);
+		goto out_free_fragment;
+	}
+
 	ret = ffa_memory_send_continue_validate(share_states, handle,
 						&share_state,
 						from_locked.vm->id, page_pool);