mirror of https://github.com/wolfSSL/wolfBoot.git
F-5672: cache NS in_vec[1].len in ARM_TEE_PS_SET to close TOCTOU double-fetch
The ARM_TEE_PS_SET branch of arm_tee_psa_call() read in_vec[1].len directly from non-secure memory four times: the WOLFBOOT_PS_MAX_DATA bounds check, the null-data guard, the copy gate, the XMEMCPY length, and the entry->size assignment. in_vec lives in NS RAM, and on ARMv8-M with AIRCR.PRIS=0 a higher-priority NS interrupt can preempt Secure thread-mode execution (and an NS-accessible DMA engine can mutate NS RAM independently) between the bounds check and the copy. An NS attacker racing either mechanism could grow the length past WOLFBOOT_PS_MAX_DATA after it was validated, overflowing the fixed entry->data[512] buffer in Secure SRAM into adjacent Secure globals. Snapshot the length once into a Secure-stack local (data_len) right after capturing the in_vec bases and use only that local for every subsequent check, the XMEMCPY operand, and entry->size. This follows the standard PSA/CMSE practice of copying NS-supplied scalars to the Secure stack before validating and using them.pull/788/head
parent
e27e81f659
commit
8cff2e8792
|
|
@ -766,16 +766,23 @@ int32_t arm_tee_psa_call(psa_handle_t handle, int32_t type,
|
|||
const void *data;
|
||||
const psa_storage_create_flags_t *flags;
|
||||
struct wolfboot_ps_entry *entry;
|
||||
size_t data_len;
|
||||
if (in_vec == NULL || in_len < 3) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
uid = (const psa_storage_uid_t *)in_vec[0].base;
|
||||
data = in_vec[1].base;
|
||||
flags = (const psa_storage_create_flags_t *)in_vec[2].base;
|
||||
/* Snapshot the NS-supplied length once into a Secure-stack local.
|
||||
* in_vec lives in NS memory and may be mutated concurrently (a
|
||||
* preempting NS interrupt or NS-accessible DMA), so re-reading
|
||||
* in_vec[1].len after the bounds check would allow a TOCTOU
|
||||
* double-fetch to grow the copy past WOLFBOOT_PS_MAX_DATA. */
|
||||
data_len = in_vec[1].len;
|
||||
if (uid == NULL || flags == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (in_vec[1].len > WOLFBOOT_PS_MAX_DATA) {
|
||||
if (data_len > WOLFBOOT_PS_MAX_DATA) {
|
||||
return PSA_ERROR_INSUFFICIENT_STORAGE;
|
||||
}
|
||||
entry = wolfboot_ps_find(*uid);
|
||||
|
|
@ -787,13 +794,13 @@ int32_t arm_tee_psa_call(psa_handle_t handle, int32_t type,
|
|||
} else if ((entry->flags & PSA_STORAGE_FLAG_WRITE_ONCE) != 0U) {
|
||||
return PSA_ERROR_NOT_PERMITTED;
|
||||
}
|
||||
if (in_vec[1].len > 0 && data == NULL) {
|
||||
if (data_len > 0 && data == NULL) {
|
||||
return PSA_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
if (in_vec[1].len > 0) {
|
||||
XMEMCPY(entry->data, data, in_vec[1].len);
|
||||
if (data_len > 0) {
|
||||
XMEMCPY(entry->data, data, data_len);
|
||||
}
|
||||
entry->size = in_vec[1].len;
|
||||
entry->size = data_len;
|
||||
entry->flags = *flags;
|
||||
return PSA_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue