fix(smccc): ensure that mpidr passed through SMC is valid
There are various SMC calls which pass mpidr as an argument which is
currently tested at random places in SMC call path.
To make the mpidr validation check consistent across SMC calls, do
this check as part of SMC argument validation.
This patch introduce a helper function is_valid_mpidr() to validate
mpidr and call it as part of validating SMC arguments at starting of
SMC handlers (which expect mpidr as an argument).
Signed-off-by: Manish Pandey <manish.pandey2@arm.com>
Change-Id: I11ea50e22caf17896cf4b2059b87029b2ba136b1
(cherry picked from commit e60c18471fc7488cc0bf1dc7eae3b43be77045a4)
diff --git a/lib/psci/psci_common.c b/lib/psci/psci_common.c
index 8d736cc..a74f105 100644
--- a/lib/psci/psci_common.c
+++ b/lib/psci/psci_common.c
@@ -610,17 +610,6 @@
}
/*******************************************************************************
- * Simple routine to determine whether a mpidr is valid or not.
- ******************************************************************************/
-int psci_validate_mpidr(u_register_t mpidr)
-{
- if (plat_core_pos_by_mpidr(mpidr) < 0)
- return PSCI_E_INVALID_PARAMS;
-
- return PSCI_E_SUCCESS;
-}
-
-/*******************************************************************************
* This function determines the full entrypoint information for the requested
* PSCI entrypoint on power on/resume and returns it.
******************************************************************************/
diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c
index a631f3f..31b1d1c 100644
--- a/lib/psci/psci_main.c
+++ b/lib/psci/psci_main.c
@@ -29,9 +29,8 @@
int rc;
entry_point_info_t ep;
- /* Determine if the cpu exists of not */
- rc = psci_validate_mpidr(target_cpu);
- if (rc != PSCI_E_SUCCESS)
+ /* Validate the target CPU */
+ if (!is_valid_mpidr(target_cpu))
return PSCI_E_INVALID_PARAMS;
/* Validate the entry point and get the entry_point_info */
@@ -219,19 +218,18 @@
int psci_affinity_info(u_register_t target_affinity,
unsigned int lowest_affinity_level)
{
- int ret;
unsigned int target_idx;
+ /* Validate the target affinity */
+ if (!is_valid_mpidr(target_affinity))
+ return PSCI_E_INVALID_PARAMS;
+
/* We dont support level higher than PSCI_CPU_PWR_LVL */
if (lowest_affinity_level > PSCI_CPU_PWR_LVL)
return PSCI_E_INVALID_PARAMS;
/* Calculate the cpu index of the target */
- ret = plat_core_pos_by_mpidr(target_affinity);
- if (ret == -1) {
- return PSCI_E_INVALID_PARAMS;
- }
- target_idx = (unsigned int)ret;
+ target_idx = (unsigned int) plat_core_pos_by_mpidr(target_affinity);
/*
* Generic management:
@@ -259,6 +257,10 @@
int rc;
u_register_t resident_cpu_mpidr;
+ /* Validate the target cpu */
+ if (!is_valid_mpidr(target_cpu))
+ return PSCI_E_INVALID_PARAMS;
+
rc = psci_spd_migrate_info(&resident_cpu_mpidr);
if (rc != PSCI_TOS_UP_MIG_CAP)
return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ?
@@ -272,8 +274,7 @@
return PSCI_E_NOT_PRESENT;
/* Check the validity of the specified target cpu */
- rc = psci_validate_mpidr(target_cpu);
- if (rc != PSCI_E_SUCCESS)
+ if (!is_valid_mpidr(target_cpu))
return PSCI_E_INVALID_PARAMS;
assert((psci_spd_pm != NULL) && (psci_spd_pm->svc_migrate != NULL));
@@ -313,8 +314,7 @@
int rc;
/* Validate target_cpu */
- rc = psci_validate_mpidr(target_cpu);
- if (rc != PSCI_E_SUCCESS)
+ if (!is_valid_mpidr(target_cpu))
return PSCI_E_INVALID_PARAMS;
/* Validate power_level against PLAT_MAX_PWR_LVL */
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index c70b377..a5929e0 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -61,13 +61,7 @@
{
int rc;
aff_info_state_t target_aff_state;
- int ret = plat_core_pos_by_mpidr(target_cpu);
- unsigned int target_idx = (unsigned int)ret;
-
- /* Calling function must supply valid input arguments */
- assert(ret >= 0);
- assert(ep != NULL);
-
+ unsigned int target_idx = (unsigned int)plat_core_pos_by_mpidr(target_cpu);
/*
* This function must only be called on platforms where the
diff --git a/lib/psci/psci_private.h b/lib/psci/psci_private.h
index 6ca9ef6..8a1e7c4 100644
--- a/lib/psci/psci_private.h
+++ b/lib/psci/psci_private.h
@@ -273,7 +273,6 @@
int psci_validate_power_state(unsigned int power_state,
psci_power_state_t *state_info);
void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info);
-int psci_validate_mpidr(u_register_t mpidr);
void psci_init_req_local_pwr_states(void);
void psci_get_target_local_pwr_states(unsigned int end_pwrlvl,
psci_power_state_t *target_state);
diff --git a/lib/psci/psci_stat.c b/lib/psci/psci_stat.c
index ecef95a..c81bbc4 100644
--- a/lib/psci/psci_stat.c
+++ b/lib/psci/psci_stat.c
@@ -181,10 +181,8 @@
psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} };
plat_local_state_t local_state;
- /* Validate the target_cpu parameter and determine the cpu index */
+ /* Determine the cpu index */
target_idx = (unsigned int) plat_core_pos_by_mpidr(target_cpu);
- if (target_idx == (unsigned int) -1)
- return PSCI_E_INVALID_PARAMS;
/* Validate the power_state parameter */
if (psci_plat_pm_ops->translate_power_state_by_mpidr == NULL)
@@ -228,6 +226,11 @@
unsigned int power_state)
{
psci_stat_t psci_stat;
+
+ /* Validate the target cpu */
+ if (!is_valid_mpidr(target_cpu))
+ return 0;
+
int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
if (rc == PSCI_E_SUCCESS)
@@ -241,6 +244,11 @@
unsigned int power_state)
{
psci_stat_t psci_stat;
+
+ /* Validate the target cpu */
+ if (!is_valid_mpidr(target_cpu))
+ return 0;
+
int rc = psci_get_stat(target_cpu, power_state, &psci_stat);
if (rc == PSCI_E_SUCCESS)