net: sockets: tls: Add flag indicating that session is closed

In case TLS session is closed at the TLS level (and thus recv() reports
0 to the application) a certain race occurs between consecutive recv()
call, and TCP session teardown. As mbedtls_ssl_read() only reports
session close upon receiving CLOSE alert, consecutive non-blocking
recv() calls would report EAGAIN instead of connection closed, if called
before underlying TCP connection was closed.

Fix this, by storing the information that TLS session has ended at TLS
socket level. The new flag will be checked before attempting further
mbed TLS actions, so that connection status is reported correctly.

Signed-off-by: Robert Lubos <robert.lubos@nordicsemi.no>
This commit is contained in:
Robert Lubos 2023-12-15 11:20:47 +01:00 committed by Fabio Baltieri
parent 1dc9028316
commit 5b3b462eed

View file

@ -123,12 +123,24 @@ struct tls_dtls_cid {
/** TLS context information. */
__net_socket struct tls_context {
/** Information whether TLS context is used. */
bool is_used;
/** Underlying TCP/UDP socket. */
int sock;
/** Information whether TLS context is used. */
bool is_used : 1;
/** Information whether TLS context was initialized. */
bool is_initialized : 1;
/** Information whether underlying socket is listening. */
bool is_listening : 1;
/** Information whether TLS handshake is currently in progress. */
bool handshake_in_progress : 1;
/** Session ended at the TLS/DTLS level. */
bool session_closed : 1;
/** Socket type. */
enum net_sock_type type;
@ -138,15 +150,6 @@ __net_socket struct tls_context {
/** Socket flags passed to a socket call. */
int flags;
/** Information whether TLS context was initialized. */
bool is_initialized;
/** Information whether underlying socket is listening. */
bool is_listening;
/** Information whether TLS handshake is currently in progress. */
bool handshake_in_progress;
/** Information whether TLS handshake is complete or not. */
struct k_sem tls_established;
@ -2202,6 +2205,10 @@ static ssize_t send_tls(struct tls_context *ctx, const void *buf,
k_timepoint_t end;
int ret;
if (ctx->session_closed) {
return 0;
}
if (!is_block) {
timeout = K_NO_WAIT;
} else {
@ -2413,6 +2420,10 @@ static ssize_t recv_tls(struct tls_context *ctx, void *buf,
k_timepoint_t end;
int ret;
if (ctx->session_closed) {
return 0;
}
if (!is_block) {
timeout = K_NO_WAIT;
} else {
@ -2431,6 +2442,7 @@ static ssize_t recv_tls(struct tls_context *ctx, void *buf,
/* Peer notified that it's closing the
* connection.
*/
ctx->session_closed = true;
break;
}
@ -2439,6 +2451,7 @@ static ssize_t recv_tls(struct tls_context *ctx, void *buf,
* supported. See mbedtls_ssl_read API
* documentation.
*/
ctx->session_closed = true;
break;
}
@ -2856,6 +2869,8 @@ static int ztls_socket_data_check(struct tls_context *ctx)
if (ret != 0) {
return -ENOMEM;
}
} else {
ctx->session_closed = true;
}
return -ENOTCONN;