Hi Ken,
I'm attaching the patch.
To repo the issue you must first make a PSA call containing outvecs and then another PSA call with NULL outvecs.
Regards, Brian
From: Ken Liu via TF-M tf-m@lists.trustedfirmware.org Sent: Wednesday, December 6, 2023 5:23 AM To: tf-m@lists.trustedfirmware.org Cc: Chung, Peter peter.chung@ti.com; nd nd@arm.com Subject: [EXTERNAL] [TF-M] Re: psa_call with NULL outvec causes a NULL pointer dereference
Hi Quach,
It is allowed to pass NULL outvecs in psa_call().
And the item reported is a true issue, and looks like the dereference is happening inside the ASSERT statement firstly. Your fix is valid and we are creating a patch to fix it. And you can push your patches as well so that we can use it directly.
We also need to check the test cases as well as this NULL vector access should be one of the test cases.
After the fix we can discuss how to update the release, before it we will have to apply one extra patch on the working branch.
Thanks for reporting this.
/Ken
From: Quach, Brian via TF-M <tf-m@lists.trustedfirmware.orgmailto:tf-m@lists.trustedfirmware.org> Sent: Wednesday, December 6, 2023 8:14 AM To: tf-m@lists.trustedfirmware.orgmailto:tf-m@lists.trustedfirmware.org Cc: Chung, Peter <peter.chung@ti.commailto:peter.chung@ti.com> Subject: [TF-M] Re: psa_call with NULL outvec causes a NULL pointer dereference
Hi,
Is it possible to call psa_call() with NULL outvecs with TF-M v2.0? I am using IPC model. This worked for me with TF-M v1.8 but now I see get a NULL pointer dereference with TF-M v2.0 when psa_reply() is called. Specifically, it happens inside update_caller_outvec_len().
It seems msg.out_size[i] is non-zero (due to a previous psa_call which had 3 outvecs). handle->caller_outvec[i].len causes a NULL pointer deference.
void update_caller_outvec_len(struct connection_t *handle) { uint32_t i;
for (i = 0; i < PSA_MAX_IOVEC; i++) { if (handle->msg.out_size[i] == 0) { continue; }
SPM_ASSERT(handle->caller_outvec[i].base == handle->outvec_base[i]);
handle->caller_outvec[i].len = handle->outvec_written[i]; } }
spm_associate_call_params() does not clear msg.out_size[] so the previous contents remain.
One potential fix is to add the highlighted code below to clear out_size[].
if (ns_access == TFM_HAL_ACCESS_NS && !PARAM_IS_NS_VEC(ctrl_param) && !PARAM_IS_NS_OUTVEC(ctrl_param)) { ns_access = 0; }
spm_memset(p_connection->msg.out_size, 0, sizeof(p_connection->msg.out_size));
/* * For client output vector, it is a PROGRAMMER ERROR if the provided * payload memory reference was invalid or not read-write. */ for (i = 0; i < ovec_num; i++) { FIH_CALL(tfm_hal_memory_check, fih_rc, curr_partition->boundary, (uintptr_t)ovecs_local[i].base, ovecs_local[i].len, TFM_HAL_ACCESS_READWRITE | ns_access); if (fih_not_eq(fih_rc, fih_int_encode(PSA_SUCCESS))) { return PSA_ERROR_PROGRAMMER_ERROR; }
p_connection->msg.out_size[i] = ovecs_local[i].len; p_connection->outvec_base[i] = ovecs_local[i].base; p_connection->outvec_written[i] = 0; }
p_connection->caller_outvec = outptr;
return PSA_SUCCESS; }
Regards,
Brian Quach SimpleLink MCU Texas Instruments Inc. 12500 TI Blvd, MS F-4000 Dallas, TX 75243 214-479-4076