VYPR
Medium severity6.3NVD Advisory· Published Jun 4, 2026

CVE-2026-5066

CVE-2026-5066

Description

Out-of-bounds read/write in Zephyr's TLS socket connect path can lead to crashes or potential code execution.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Out-of-bounds read/write in Zephyr's TLS socket connect path can lead to crashes or potential code execution.

Vulnerability

An out-of-bounds write or read vulnerability exists in the TLS socket connect path of the network sockets subsystem in Zephyr, specifically within sockets_tls.c. This issue occurs when the TLS session cache is enabled. The functions tls_session_store() and tls_session_restore() use memcpy to copy a caller-supplied address into a fixed-size buffer. The addrlen value, controlled by the caller, is not validated against the destination buffer size, which is sizeof(struct net_sockaddr). This can lead to reading or writing past the allocated memory for the TLS session cache's address. Affected versions are not explicitly listed but the vulnerability is present in the described code path [1].

Exploitation

An attacker can exploit this vulnerability by establishing a TLS socket connection when the TLS session cache is enabled. The attacker needs to provide a value for addrlen that is larger than sizeof(struct net_sockaddr), for example, 128 bytes, when calling the connect function. This incorrect addrlen will be passed to tls_session_store() and tls_session_restore(), triggering the vulnerable memcpy operations [1].

Impact

Successful exploitation of this out-of-bounds write/read vulnerability can lead to a crash of the affected system, resulting in a denial of service. Furthermore, depending on the specific memory layout and attacker's ability to control the data being written, it may be possible to achieve arbitrary code execution [1].

Mitigation

This vulnerability has been addressed in the Zephyr project. The recommended mitigation is to update to a patched version of Zephyr. The advisory indicates that struct net_sockaddr_storage should be used instead for storing addresses in the cache, and input validation for addrlen should be implemented. No specific fixed version or release date is provided in the available references, nor is there information about workarounds or End-of-Life status [1].

AI Insight generated on Jun 4, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

5
ef75a302bf3b

doc: vuln: Add CVE under embargo

https://github.com/zephyrproject-rtos/zephyrFlavio CeolinMar 27, 2026via github-commit-search
1 file changed · +5 0
  • doc/security/vulnerabilities.rst+5 0 modified
    @@ -2212,3 +2212,8 @@ This has been fixed in main for v4.4.0
     
     - `PR 104390 fix for main
       <https://github.com/zephyrproject-rtos/zephyr/pull/104390>`_
    +
    +:cve:`2026-5066`
    +----------------
    +
    +Under embargo until 2026-06-01
    
16aded5d1fa8

net: lib: sockets: tls: Use struct net_sockaddr_storage for stack variables

https://github.com/zephyrproject-rtos/zephyrPieter De GendtMar 4, 2026via body-scan-shorthand
1 file changed · +20 20
  • subsys/net/lib/sockets/sockets_tls.c+20 20 modified
    @@ -994,15 +994,15 @@ static int dtls_server_rx(void *ctx, unsigned char *buf, size_t len)
     {
     	struct tls_context *tls_ctx = ctx;
     	net_socklen_t addrlen = sizeof(struct net_sockaddr);
    -	struct net_sockaddr addr;
    +	struct net_sockaddr_storage addr;
     	int err;
     	ssize_t received;
     	uint8_t tmp_buf;
     
     	/* Peek the packet first to check the peer address. */
     	received = zsock_recvfrom(tls_ctx->sock, &tmp_buf, sizeof(tmp_buf),
     				  ZSOCK_MSG_DONTWAIT | ZSOCK_MSG_PEEK,
    -				  &addr, &addrlen);
    +				  net_sad(&addr), &addrlen);
     	if (received < 0) {
     		if (errno == EAGAIN) {
     			return MBEDTLS_ERR_SSL_WANT_READ;
    @@ -1014,7 +1014,7 @@ static int dtls_server_rx(void *ctx, unsigned char *buf, size_t len)
     
     	/* Check if the peer address matches the current session. */
     	if (tls_ctx->active_session->dtls_peer_addrlen != 0 &&
    -	    !dtls_is_peer_addr_valid(tls_ctx->active_session, &addr, addrlen)) {
    +	    !dtls_is_peer_addr_valid(tls_ctx->active_session, net_sad(&addr), addrlen)) {
     		/* Peer address does not match the current session, exit now
     		 * and try to find the appropriate session or allocate a new one.
     		 */
    @@ -1023,7 +1023,7 @@ static int dtls_server_rx(void *ctx, unsigned char *buf, size_t len)
     
     	/* If the session matches, read the actual packet. */
     	received = zsock_recvfrom(tls_ctx->sock, buf, len,
    -				  ZSOCK_MSG_DONTWAIT, &addr, &addrlen);
    +				  ZSOCK_MSG_DONTWAIT, net_sad(&addr), &addrlen);
     	if (received < 0) {
     		NET_ERR("DTLS server RX: failure %d", errno);
     		return MBEDTLS_ERR_NET_RECV_FAILED;
    @@ -1033,7 +1033,7 @@ static int dtls_server_rx(void *ctx, unsigned char *buf, size_t len)
     
     	/* Only allow to store peer address for DTLS servers. */
     	if (tls_ctx->active_session->dtls_peer_addrlen == 0) {
    -		dtls_peer_address_set(tls_ctx->active_session, &addr, addrlen);
    +		dtls_peer_address_set(tls_ctx->active_session, net_sad(&addr), addrlen);
     
     		err = mbedtls_ssl_set_client_transport_id(&tls_ctx->active_session->ssl,
     							 (const unsigned char *)&addr,
    @@ -1050,11 +1050,11 @@ static int dtls_client_rx(void *ctx, unsigned char *buf, size_t len)
     {
     	struct tls_context *tls_ctx = ctx;
     	net_socklen_t addrlen = sizeof(struct net_sockaddr);
    -	struct net_sockaddr addr;
    +	struct net_sockaddr_storage addr;
     	ssize_t received;
     
     	received = zsock_recvfrom(tls_ctx->sock, buf, len,
    -				  ZSOCK_MSG_DONTWAIT, &addr, &addrlen);
    +				  ZSOCK_MSG_DONTWAIT, net_sad(&addr), &addrlen);
     	if (received < 0) {
     		if (errno == EAGAIN) {
     			return MBEDTLS_ERR_SSL_WANT_READ;
    @@ -1070,7 +1070,7 @@ static int dtls_client_rx(void *ctx, unsigned char *buf, size_t len)
     		return MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED;
     	}
     
    -	if (!dtls_is_peer_addr_valid(tls_ctx->active_session, &addr, addrlen)) {
    +	if (!dtls_is_peer_addr_valid(tls_ctx->active_session, net_sad(&addr), addrlen)) {
     		/* Received packet from a different peer, drop and retry. */
     		return MBEDTLS_ERR_SSL_WANT_READ;
     	}
    @@ -1168,7 +1168,7 @@ static int dtls_server_switch_active_session_by_cid(struct tls_context *tls_ctx)
     	k_mutex_lock(&dtls_helper_buf_lock, K_FOREVER);
     
     	SYS_SLIST_FOR_EACH_CONTAINER(&tls_ctx->sessions, session_ctx, node) {
    -		struct net_sockaddr addr;
    +		struct net_sockaddr_storage addr;
     		net_socklen_t addrlen;
     		int cid_enabled;
     		ssize_t len;
    @@ -1198,7 +1198,7 @@ static int dtls_server_switch_active_session_by_cid(struct tls_context *tls_ctx)
     		addrlen = sizeof(struct net_sockaddr);
     		len = zsock_recvfrom(tls_ctx->sock, &dtls_helper_buf, sizeof(dtls_helper_buf),
     				     ZSOCK_MSG_DONTWAIT | ZSOCK_MSG_PEEK,
    -				     &addr, &addrlen);
    +				     net_sad(&addr), &addrlen);
     		if (len < 0) {
     			result = -errno;
     			break;
    @@ -1207,11 +1207,11 @@ static int dtls_server_switch_active_session_by_cid(struct tls_context *tls_ctx)
     		ret = mbedtls_ssl_check_record(&session_ctx->ssl, dtls_helper_buf, len);
     		if (ret == 0) {
     			NET_DBG("Found matching session (CID) for [%s]:%d (was [%s]:%d)",
    -				LOG_ADDR_PORT_HELPER(&addr),
    +				LOG_ADDR_PORT_HELPER(net_sad(&addr)),
     				LOG_ADDR_PORT_HELPER(net_sad(&session_ctx->dtls_peer_addr)));
     
     			/* Need to update peer address as CID matched */
    -			dtls_peer_address_set(session_ctx, &addr, addrlen);
    +			dtls_peer_address_set(session_ctx, net_sad(&addr), addrlen);
     			tls_ctx->active_session = session_ctx;
     			result = 0;
     			break;
    @@ -1234,20 +1234,20 @@ static int dtls_server_switch_active_session_by_cid(struct tls_context *tls_ctx)
     static int dtls_server_switch_session_on_rx(struct tls_context *tls_ctx)
     {
     	net_socklen_t addrlen = sizeof(struct net_sockaddr);
    -	struct net_sockaddr addr;
    +	struct net_sockaddr_storage addr;
     	uint8_t tmp_buf;
     	int ret;
     
     	/* Peek a dummy byte first to get peer address. */
     	ret = zsock_recvfrom(tls_ctx->sock, &tmp_buf, sizeof(tmp_buf),
     			     ZSOCK_MSG_DONTWAIT | ZSOCK_MSG_PEEK,
    -			     &addr, &addrlen);
    +			     net_sad(&addr), &addrlen);
     	if (ret < 0) {
     		return -errno;
     	}
     
     	/* Try to match existing session by peer address. */
    -	ret = dtls_server_switch_active_session(tls_ctx, &addr, addrlen);
    +	ret = dtls_server_switch_active_session(tls_ctx, net_sad(&addr), addrlen);
     	if (ret == 0 || ret == 1) {
     		return ret;
     	}
    @@ -1262,7 +1262,7 @@ static int dtls_server_switch_session_on_rx(struct tls_context *tls_ctx)
     
     	NET_DBG("No session found (RX), allocating new");
     
    -	ret = dtls_server_new_active_session(tls_ctx, &addr, addrlen);
    +	ret = dtls_server_new_active_session(tls_ctx, net_sad(&addr), addrlen);
     	if (ret < 0) {
     		NET_ERR("Failed to allocate new session for DTLS server, "
     			"dropping packet (err: %d)", ret);
    @@ -3613,8 +3613,8 @@ static ssize_t recvfrom_dtls_server(struct tls_context *ctx, void *buf,
     	 * a socket.
     	 */
     	do {
    -		net_socklen_t peer_addrlen = sizeof(struct net_sockaddr);
    -		struct net_sockaddr peer_addr;
    +		struct net_sockaddr_storage peer_addr;
    +		net_socklen_t peer_addrlen = sizeof(peer_addr);
     
     		repeat = false;
     
    @@ -3652,7 +3652,7 @@ static ssize_t recvfrom_dtls_server(struct tls_context *ctx, void *buf,
     		}
     
     		/* Backup peer address (to verify later if it changed). */
    -		dtls_peer_address_get(ctx->active_session, &peer_addr, &peer_addrlen);
    +		dtls_peer_address_get(ctx->active_session, net_sad(&peer_addr), &peer_addrlen);
     
     		ret = recvfrom_dtls_common(ctx, buf, max_len, flags,
     					   src_addr, addrlen);
    @@ -3682,7 +3682,7 @@ static ssize_t recvfrom_dtls_server(struct tls_context *ctx, void *buf,
     		case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
     		case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
     			if (peer_addrlen > 0 &&
    -			    !dtls_is_peer_addr_valid(ctx->active_session, &peer_addr,
    +			    !dtls_is_peer_addr_valid(ctx->active_session, net_sad(&peer_addr),
     						     peer_addrlen)) {
     				/* Current peer changed, repeat the loop. */
     				repeat = true;
    
f03471abbde9

net: lib: sockets: tls: Validate addrlen before memcpy

https://github.com/zephyrproject-rtos/zephyrPieter De GendtMar 4, 2026via body-scan-shorthand
1 file changed · +8 0
  • subsys/net/lib/sockets/sockets_tls.c+8 0 modified
    @@ -674,6 +674,10 @@ static void tls_session_store(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    @@ -704,6 +708,10 @@ static void tls_session_restore(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    
b76136583a17

net: lib: sockets: tls: Validate addrlen before memcpy

https://github.com/zephyrproject-rtos/zephyrPieter De GendtMar 4, 2026via body-scan-shorthand
1 file changed · +8 0
  • subsys/net/lib/sockets/sockets_tls.c+8 0 modified
    @@ -678,6 +678,10 @@ static void tls_session_store(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    @@ -708,6 +712,10 @@ static void tls_session_restore(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    
21e9b94826db

net: lib: sockets: tls: Validate addrlen before memcpy

https://github.com/zephyrproject-rtos/zephyrPieter De GendtMar 4, 2026via body-scan-shorthand
1 file changed · +8 0
  • subsys/net/lib/sockets/sockets_tls.c+8 0 modified
    @@ -678,6 +678,10 @@ static void tls_session_store(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    @@ -708,6 +712,10 @@ static void tls_session_restore(struct tls_context *context,
     		return;
     	}
     
    +	if (addrlen > sizeof(peer_addr)) {
    +		return;
    +	}
    +
     	memcpy(&peer_addr, addr, addrlen);
     	mbedtls_ssl_session_init(&session);
     
    

Vulnerability mechanics

Root cause

"The TLS session cache functions incorrectly copy caller-supplied address data into fixed-size buffers without validating the length against the destination buffer size."

Attack vector

An attacker can trigger this vulnerability by establishing a TLS connection with a specially crafted `addrlen` value that exceeds the size of the destination buffer within the `tls_session_store()` and `tls_session_restore()` functions. This occurs when the TLS session cache is enabled, leading to an out-of-bounds write. The PoC demonstrates passing an `addrlen` of 128 bytes to the `zsock_connect` function, which then propagates to the vulnerable memcpy operations [ref_id=1].

Affected code

The vulnerability resides in the `tls_session_store()` and `tls_session_restore()` functions within `subsys/net/lib/sockets/sockets_tls.c`. These functions perform a `memcpy` operation using a caller-controlled `addrlen` without validating it against the size of the destination buffer, `peer_addr` [ref_id=1].

What the fix does

The patch addresses the vulnerability by adding a validation check before the `memcpy` operation in `tls_session_store()` and `tls_session_restore()`. This check ensures that `addrlen` does not exceed the size of the `peer_addr` buffer, preventing any out-of-bounds writes [patch_id=4856403, patch_id=4856082]. Additionally, the patch replaces `struct net_sockaddr` with `struct net_sockaddr_storage` for stack variables to better accommodate address storage [patch_id=4856080].

Preconditions

  • configCONFIG_NET_SOCKETS_TLS must be enabled.
  • configCONFIG_NET_SOCKETS_TLS_MAX_CLIENT_SESSION_COUNT must be greater than 0, enabling the TLS session cache.
  • inputA TLS connection attempt with an `addrlen` value larger than the size of the destination buffer used for storing peer addresses.

Generated on Jun 4, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

1

News mentions

0

No linked articles in our index yet.