Skip to content

Commit 93d0a76

Browse files
committed
net: sockets: tls: Block DTLS client in poll until handshake is complete
When DTLS client was added to `poll` before/during the handshake, it could throw errors and in some circumstances (when polling thread was cooperative and had higher or equal priority to the handshake thread) could lead to a deadlock in the application. Prevent that, by blocking on handshake semaphore instead of fifo. Poll will start using fifo for data poll only after handshake is complete. Signed-off-by: Robert Lubos <[email protected]>
1 parent 7b39d79 commit 93d0a76

File tree

1 file changed

+57
-20
lines changed

1 file changed

+57
-20
lines changed

subsys/net/lib/sockets/sockets_tls.c

Lines changed: 57 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1666,27 +1666,39 @@ static int ztls_poll_prepare_ctx(struct net_context *ctx,
16661666
}
16671667

16681668
if (pfd->events & ZSOCK_POLLIN) {
1669-
if (!IS_LISTENING(ctx)) {
1670-
/* If there already is mbedTLS data to read, there is no
1671-
* need to set the k_poll_event object. Return EALREADY
1672-
* so we won't block in the k_poll.
1673-
*/
1674-
if (mbedtls_ssl_get_bytes_avail(&ctx->tls->ssl) > 0) {
1675-
errno = EALREADY;
1676-
return -1;
1677-
}
1678-
}
1679-
16801669
if (*pev == pev_end) {
16811670
errno = ENOMEM;
16821671
return -1;
16831672
}
16841673

1685-
(*pev)->obj = &ctx->recv_q;
1686-
(*pev)->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
1674+
/* DTLS client should wait for the handshake to complete before
1675+
* it actually starts to poll for data.
1676+
*/
1677+
if (net_context_get_type(ctx) == SOCK_DGRAM &&
1678+
ctx->tls->options.role == MBEDTLS_SSL_IS_CLIENT &&
1679+
!is_handshake_complete(ctx)) {
1680+
(*pev)->obj = &ctx->tls->tls_established;
1681+
(*pev)->type = K_POLL_TYPE_SEM_AVAILABLE;
1682+
} else {
1683+
/* Otherwise, monitor fifo for data/connections. */
1684+
(*pev)->obj = &ctx->recv_q;
1685+
(*pev)->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
1686+
}
1687+
16871688
(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
16881689
(*pev)->state = K_POLL_STATE_NOT_READY;
16891690
(*pev)++;
1691+
1692+
/* If there already is mbedTLS data to read, there is no
1693+
* need to set the k_poll_event object. Return EALREADY
1694+
* so we won't block in the k_poll.
1695+
*/
1696+
if (!IS_LISTENING(ctx)) {
1697+
if (mbedtls_ssl_get_bytes_avail(&ctx->tls->ssl) > 0) {
1698+
errno = EALREADY;
1699+
return -1;
1700+
}
1701+
}
16901702
}
16911703

16921704
return 0;
@@ -1707,19 +1719,34 @@ static int ztls_poll_update_ctx(struct net_context *ctx,
17071719
}
17081720

17091721
if (pfd->events & ZSOCK_POLLIN) {
1722+
/* Check if socket was waiting for the handshake to complete. */
1723+
if ((*pev)->obj == &ctx->tls->tls_established) {
1724+
if ((*pev)->state == K_POLL_STATE_NOT_READY) {
1725+
goto next;
1726+
}
1727+
1728+
/* Reconfigure the poll event to wait for data now. */
1729+
(*pev)->obj = &ctx->recv_q;
1730+
(*pev)->type = K_POLL_TYPE_FIFO_DATA_AVAILABLE;
1731+
(*pev)->mode = K_POLL_MODE_NOTIFY_ONLY;
1732+
(*pev)->state = K_POLL_STATE_NOT_READY;
1733+
1734+
goto again;
1735+
}
1736+
17101737
if (!IS_LISTENING(ctx)) {
17111738
/* Already had TLS data to read on socket. */
17121739
if (mbedtls_ssl_get_bytes_avail(&ctx->tls->ssl) > 0) {
17131740
pfd->revents |= ZSOCK_POLLIN;
1714-
return 0;
1741+
goto next;
17151742
}
17161743
}
17171744

17181745
/* Some encrypted data received on the socket. */
1719-
if (((*pev)++)->state != K_POLL_STATE_NOT_READY) {
1746+
if ((*pev)->state != K_POLL_STATE_NOT_READY) {
17201747
if (IS_LISTENING(ctx)) {
17211748
pfd->revents |= ZSOCK_POLLIN;
1722-
return 0;
1749+
goto next;
17231750
}
17241751

17251752
/* EAGAIN might happen during or just after
@@ -1728,25 +1755,35 @@ static int ztls_poll_update_ctx(struct net_context *ctx,
17281755
if (recv(pfd->fd, NULL, 0, ZSOCK_MSG_DONTWAIT) < 0 &&
17291756
errno != EAGAIN) {
17301757
pfd->revents |= ZSOCK_POLLERR;
1731-
return 0;
1758+
goto next;
17321759
}
17331760

17341761
if (mbedtls_ssl_get_bytes_avail(&ctx->tls->ssl) > 0 ||
17351762
sock_is_eof(ctx)) {
17361763
pfd->revents |= ZSOCK_POLLIN;
1737-
return 0;
1764+
goto next;
17381765
}
17391766

17401767
/* Received encrypted data, but still not enough
17411768
* to decrypt it and return data through socket,
17421769
* ask for retry.
17431770
*/
1744-
errno = EAGAIN;
1745-
return -1;
1771+
1772+
(*pev)->state = K_POLL_STATE_NOT_READY;
1773+
goto again;
17461774
}
17471775
}
17481776

17491777
return 0;
1778+
1779+
next:
1780+
(*pev)++;
1781+
return 0;
1782+
1783+
again:
1784+
(*pev)++;
1785+
errno = EAGAIN;
1786+
return -1;
17501787
}
17511788

17521789
int ztls_getsockopt_ctx(struct net_context *ctx, int level, int optname,

0 commit comments

Comments
 (0)