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.org>
Sent: Wednesday, December 6, 2023 8:14 AM
To: tf-m@lists.trustedfirmware.org
Cc: Chung, Peter <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