fix(sdei): return SDEI_EINVAL if signaling state is incorrect

In case a step is omitted when an SDEI event is registered,
enabled, unmasked and then signaled, incorrect code paths
may be reached.

This patch adds additional checks to return early from such
an incorrect state.

Change-Id: Ia2753e9a1b95544e1afa72603574fe830f51ea9f
Signed-off-by: Igor Podgainõi <igor.podgainoi@arm.com>
Signed-off-by: Mark Dykes <mark.dykes@arm.com>
diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c
index 01cc131..bbc9f73 100644
--- a/services/std_svc/sdei/sdei_main.c
+++ b/services/std_svc/sdei/sdei_main.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -910,25 +910,54 @@
 /* Send a signal to another SDEI client PE */
 static int sdei_signal(int ev_num, uint64_t target_pe)
 {
+	unsigned int i;
 	sdei_ev_map_t *map;
+	sdei_ev_map_t *map_priv;
+	sdei_entry_t *se;
 
 	/* Only event 0 can be signalled */
-	if (ev_num != SDEI_EVENT_0)
+	if (ev_num != SDEI_EVENT_0) {
 		return SDEI_EINVAL;
+	}
 
 	/* Find mapping for event 0 */
 	map = find_event_map(SDEI_EVENT_0);
-	if (map == NULL)
+	if (map == NULL) {
 		return SDEI_EINVAL;
+	}
 
 	/* The event must be signalable */
-	if (!is_event_signalable(map))
+	if (!is_event_signalable(map)) {
 		return SDEI_EINVAL;
+	}
 
 	/* Validate target */
-	if (!is_valid_mpidr(target_pe))
+	if (!is_valid_mpidr(target_pe)) {
+		return SDEI_EINVAL;
+	}
+
+	/* The event must be unmasked */
+	if (sdei_is_target_pe_masked(target_pe)) {
 		return SDEI_EINVAL;
+	}
 
+	/* The event must be registered and enabled */
+	if (is_event_private(map)) {
+		map_priv = SDEI_PRIVATE_MAPPING()->map;
+		for (i = 0; i < SDEI_PRIVATE_MAPPING()->num_maps; i++) {
+			if (map_priv->ev_num == SDEI_EVENT_0) {
+				se = get_event_entry_target_pe((long int) i,
+				(unsigned int) SDEI_PRIVATE_MAPPING()->num_maps, target_pe);
+				if (!(GET_EV_STATE((se), REGISTERED))) {
+					return SDEI_EINVAL;
+				}
+				if (!(GET_EV_STATE((se), ENABLED))) {
+					return SDEI_EINVAL;
+				}
+			}
+			map_priv++;
+		}
+	}
 	/* Raise SGI. Platform will validate target_pe */
 	plat_ic_raise_el3_sgi((int) map->intr, (u_register_t) target_pe);