CVE-2026-12233
Full vulnerability record from the local CVENow database.
Description
The PSA Protected Storage credential backend (subsys/net/lib/tls_credentials/tls_credentials_trusted.c) declared its credential-store mutex as a plain zero-filled static struct k_mutex credential_lock; and never called k_mutex_init() on it. A statically zero-filled k_mutex has an uninitialized wait queue (its dlist head/tail are NULL instead of the self-referential sentinels that k_mutex_init/K_MUTEX_DEFINE install). The uncontended lock path does not touch the wait queue, so the defect is latent and serialized use behaves correctly. When two execution contexts contend on the lock, k_mutex_lock() pends the blocking thread on the wait queue via z_pend_curr(), which calls sys_dlist_append() on the zeroed list and dereferences a NULL tail pointer (tail->next = node), faulting the kernel. The lock is held during TLS handshake credential loading and by all credential add/get/delete operations, so a deployment performing concurrent TLS handshakes (for example a server handling multiple simultaneous connections from a remote peer) or a credential-management operation concurrent with a handshake can trigger the dereference. The impact is a denial of service: a deterministic kernel panic / device reset on the first contention. There is no memory corruption beyond the NULL dereference and no confidentiality or integrity impact; mutual exclusion on the fast path remains correct. Exposure is limited to builds with CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE enabled (PSA Protected Storage / TF-M platforms); the default volatile RAM backend initializes its lock correctly and is unaffected. The fix initializes the mutex statically with K_MUTEX_DEFINE(credential_lock), providing a valid wait queue so the contended path no longer touches a NULL list.
View original CVE JSON
{
"id": "CVE-2026-12233",
"sourceIdentifier": "[email protected]",
"published": "2026-08-12T05:17:42.010",
"lastModified": "2026-10-23T20:10:00.160",
"vulnStatus": "Awaiting Analysis",
"cveTags": [],
"descriptions": [
{
"lang": "en",
"value": "The PSA Protected Storage credential backend (subsys/net/lib/tls_credentials/tls_credentials_trusted.c) declared its credential-store mutex as a plain zero-filled static struct k_mutex credential_lock; and never called k_mutex_init() on it. A statically zero-filled k_mutex has an uninitialized wait queue (its dlist head/tail are NULL instead of the self-referential sentinels that k_mutex_init/K_MUTEX_DEFINE install). The uncontended lock path does not touch the wait queue, so the defect is latent and serialized use behaves correctly.\n\nWhen two execution contexts contend on the lock, k_mutex_lock() pends the blocking thread on the wait queue via z_pend_curr(), which calls sys_dlist_append() on the zeroed list and dereferences a NULL tail pointer (tail->next = node), faulting the kernel. The lock is held during TLS handshake credential loading and by all credential add/get/delete operations, so a deployment performing concurrent TLS handshakes (for example a server handling multiple simultaneous connections from a remote peer) or a credential-management operation concurrent with a handshake can trigger the dereference.\n\nThe impact is a denial of service: a deterministic kernel panic / device reset on the first contention. There is no memory corruption beyond the NULL dereference and no confidentiality or integrity impact; mutual exclusion on the fast path remains correct. Exposure is limited to builds with CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE enabled (PSA Protected Storage / TF-M platforms); the default volatile RAM backend initializes its lock correctly and is unaffected.\n\nThe fix initializes the mutex statically with K_MUTEX_DEFINE(credential_lock), providing a valid wait queue so the contended path no longer touches a NULL list."
},
{
"lang": "es",
"value": "El backend de credenciales de PSA Protected Storage (subsys/net/lib/tls_credentials/tls_credentials_trusted.c) declaró su mutex de almacén de credenciales como una struct k_mutex credential_lock estática simple rellenada con ceros; y nunca llamó a k_mutex_init() sobre ella. Un k_mutex rellenado con ceros estáticamente tiene una cola de espera no inicializada (su cabeza/cola de dlist son NULL en lugar de los centinelas autorreferenciales que instalan k_mutex_init/K_MUTEX_DEFINE). La ruta de bloqueo sin contención no toca la cola de espera, por lo que el defecto es latente y el uso serializado se comporta correctamente.\n\nCuando dos contextos de ejecución compiten por el bloqueo, k_mutex_lock() suspende el hilo bloqueante en la cola de espera a través de z_pend_curr(), que llama a sys_dlist_append() en la lista con ceros y desreferencia un puntero de cola NULL (tail -> next = node), provocando un fallo en el kernel. El bloqueo se mantiene durante la carga de credenciales del handshake TLS y por todas las operaciones de añadir/obtener/eliminar credenciales, por lo que un despliegue que realice handshakes TLS concurrentes (por ejemplo, un servidor que maneja múltiples conexiones simultáneas de un par remoto) o una operación de gestión de credenciales concurrente con un handshake puede desencadenar la desreferencia.\n\nEl impacto es una denegación de servicio: un pánico de kernel determinista / reinicio del dispositivo en la primera contención. No hay corrupción de memoria más allá de la desreferencia NULL y ningún impacto en la confidencialidad o integridad; la exclusión mutua en la ruta rápida sigue siendo correcta. La exposición se limita a las compilaciones con CONFIG_TLS_CREDENTIALS_BACKEND_PROTECTED_STORAGE habilitado (plataformas PSA Protected Storage / TF-M); el backend de RAM volátil predeterminado inicializa su bloqueo correctamente y no se ve afectado.\n\nLa solución inicializa el mutex estáticamente con K_MUTEX_DEFINE(credential_lock), proporcionando una cola de espera válida para que la ruta con contención ya no toque una lista NULL."
}
],
"affected": [
{
"source": "[email protected]",
"affectedData": [
{
"vendor": "zephyrproject",
"product": "zephyr",
"defaultStatus": "unaffected",
"collectionURL": "https://github.com/zephyrproject-rtos/zephyr",
"packageName": "zephyr",
"programFiles": [
"subsys/net/lib/tls_credentials/tls_credentials_trusted.c"
],
"versions": [
{
"version": "3.2.0",
"lessThan": "4.4.2",
"versionType": "semver",
"status": "affected"
}
]
}
]
}
],
"metrics": {
"cvssMetricV31": [
{
"source": "[email protected]",
"type": "Secondary",
"cvssData": {
"version": "3.1",
"vectorString": "CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:N/I:N/A:H",
"baseScore": 5.9,
"baseSeverity": "MEDIUM",
"attackVector": "NETWORK",
"attackComplexity": "HIGH",
"privilegesRequired": "NONE",
"userInteraction": "NONE",
"scope": "UNCHANGED",
"confidentialityImpact": "NONE",
"integrityImpact": "NONE",
"availabilityImpact": "HIGH"
},
"exploitabilityScore": 2.2,
"impactScore": 3.6
}
],
"ssvcV203": [
{
"source": "134c704f-9b21-4f2e-91b3-4a467353bcc0",
"ssvcData": {
"timestamp": "2026-08-13T15:09:49.771424Z",
"id": "CVE-2026-12233",
"options": [
{
"exploitation": "none"
},
{
"automatable": "no"
},
{
"technicalImpact": "partial"
}
],
"role": "CISA Coordinator",
"version": "2.0.3"
}
}
]
},
"weaknesses": [
{
"source": "[email protected]",
"type": "Secondary",
"description": [
{
"lang": "en",
"value": "CWE-665"
}
]
}
],
"references": [
{
"url": "https://github.com/zephyrproject-rtos/zephyr/commit/29581d586f3d68ec8bb1448b522e5470d4a06aa9",
"source": "[email protected]"
},
{
"url": "https://github.com/zephyrproject-rtos/zephyr/security/advisories/GHSA-57c4-xcq2-fqj7",
"source": "[email protected]"
}
]
}