fix(protocol): retry EINTR on receive and clamp SSL_write length
protocol_receive_n_data_until() aborted on a signal-interrupted plaintext read (and on SSL_ERROR_SYSCALL with errno==EINTR); retry both, matching the send path and protocol_read_status_until(). Also clamp each SSL_write() to INT_MAX so a >INT_MAX size_t request can never truncate into a partial write.
This commit is contained in:
+14
-3
@@ -302,10 +302,14 @@ bool protocol_send_n_data(ProtocolSession* session, const void* data, size_t dat
|
|||||||
if (pfd.revents & (POLLERR | POLLNVAL))
|
if (pfd.revents & (POLLERR | POLLNVAL))
|
||||||
return false;
|
return false;
|
||||||
ssize_t bytes_send;
|
ssize_t bytes_send;
|
||||||
if (session->ssl)
|
if (session->ssl) {
|
||||||
bytes_send = SSL_write(session->ssl, (const char*)data + total_bytes_send, chunk);
|
/* SSL_write takes an int length; clamp a >INT_MAX request into chunks so
|
||||||
else
|
* the size_t downcast can never truncate into a negative/partial write. */
|
||||||
|
size_t ssl_chunk = chunk > (size_t)INT_MAX ? (size_t)INT_MAX : chunk;
|
||||||
|
bytes_send = SSL_write(session->ssl, (const char*)data + total_bytes_send, (int)ssl_chunk);
|
||||||
|
} else {
|
||||||
bytes_send = write(fd, (const char*)data + total_bytes_send, chunk);
|
bytes_send = write(fd, (const char*)data + total_bytes_send, chunk);
|
||||||
|
}
|
||||||
if (bytes_send <= 0) {
|
if (bytes_send <= 0) {
|
||||||
if (session->ssl) {
|
if (session->ssl) {
|
||||||
int ssl_err = SSL_get_error(session->ssl, (int)bytes_send);
|
int ssl_err = SSL_get_error(session->ssl, (int)bytes_send);
|
||||||
@@ -387,6 +391,13 @@ static bool protocol_receive_n_data_until(ProtocolSession* session, void* data,
|
|||||||
wait_events = ssl_err == SSL_ERROR_WANT_WRITE ? POLLOUT : POLLIN;
|
wait_events = ssl_err == SSL_ERROR_WANT_WRITE ? POLLOUT : POLLIN;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
/* A signal interrupts the blocking TLS read: retry (mirrors the send
|
||||||
|
path and protocol_read_status_until) so the loop reaches its next
|
||||||
|
abort/deadline checkpoint instead of failing spuriously. */
|
||||||
|
if (ssl_err == SSL_ERROR_SYSCALL && errno == EINTR)
|
||||||
|
continue;
|
||||||
|
} else if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (bytes_received == 0)
|
if (bytes_received == 0)
|
||||||
log_message(LOG_LEVEL_ERROR, "Connection closed while receiving data");
|
log_message(LOG_LEVEL_ERROR, "Connection closed while receiving data");
|
||||||
|
|||||||
Reference in New Issue
Block a user