Fixing crash during TLS connection shutdown.
A crash was caused by an incorrect timer handler nxt_h1p_idle_timeout() if SSL_shutdown() returned SSL_ERROR_WANT_READ/SSL_ERROR_WANT_WRITE. The flag SSL_RECEIVED_SHUTDOWN is used to avoid getting SSL_ERROR_WANT_READ, so the server won't wait for a close notification from a client. For SSL_ERROR_WANT_WRITE, a correct timer handler is set up.
This commit is contained in:
@@ -68,6 +68,12 @@ compatibility with Ruby 3.0.
|
|||||||
</para>
|
</para>
|
||||||
</change>
|
</change>
|
||||||
|
|
||||||
|
<change type="bugfix">
|
||||||
|
<para>
|
||||||
|
the router process could crash while closing TLS connection.
|
||||||
|
</para>
|
||||||
|
</change>
|
||||||
|
|
||||||
<change type="bugfix">
|
<change type="bugfix">
|
||||||
<para>
|
<para>
|
||||||
a segmentation fault might have occurred in the PHP module if
|
a segmentation fault might have occurred in the PHP module if
|
||||||
|
|||||||
0
src/nxt_h1proto.c
Normal file → Executable file
0
src/nxt_h1proto.c
Normal file → Executable file
@@ -66,6 +66,8 @@ static void nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj,
|
|||||||
void *data);
|
void *data);
|
||||||
static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c,
|
static nxt_int_t nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c,
|
||||||
int ret, nxt_err_t sys_err, nxt_openssl_io_t io);
|
int ret, nxt_err_t sys_err, nxt_openssl_io_t io);
|
||||||
|
static void nxt_openssl_conn_io_shutdown_timeout(nxt_task_t *task, void *obj,
|
||||||
|
void *data);
|
||||||
static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task,
|
static void nxt_cdecl nxt_openssl_conn_error(nxt_task_t *task,
|
||||||
nxt_err_t err, const char *fmt, ...);
|
nxt_err_t err, const char *fmt, ...);
|
||||||
static nxt_uint_t nxt_openssl_log_error_level(nxt_err_t err);
|
static nxt_uint_t nxt_openssl_log_error_level(nxt_err_t err);
|
||||||
@@ -839,11 +841,7 @@ nxt_openssl_conn_init(nxt_task_t *task, nxt_tls_conf_t *conf, nxt_conn_t *c)
|
|||||||
c->sendfile = NXT_CONN_SENDFILE_OFF;
|
c->sendfile = NXT_CONN_SENDFILE_OFF;
|
||||||
|
|
||||||
nxt_openssl_conn_handshake(task, c, c->socket.data);
|
nxt_openssl_conn_handshake(task, c, c->socket.data);
|
||||||
/*
|
|
||||||
* TLS configuration might be destroyed after the TLS connection
|
|
||||||
* is established.
|
|
||||||
*/
|
|
||||||
tls->conf = NULL;
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@@ -1099,6 +1097,10 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
|||||||
|
|
||||||
SSL_set_quiet_shutdown(s, quiet);
|
SSL_set_quiet_shutdown(s, quiet);
|
||||||
|
|
||||||
|
if (tls->conf->no_wait_shutdown) {
|
||||||
|
mode |= SSL_RECEIVED_SHUTDOWN;
|
||||||
|
}
|
||||||
|
|
||||||
once = 1;
|
once = 1;
|
||||||
|
|
||||||
for ( ;; ) {
|
for ( ;; ) {
|
||||||
@@ -1153,7 +1155,8 @@ nxt_openssl_conn_io_shutdown(nxt_task_t *task, void *obj, void *data)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case NXT_AGAIN:
|
case NXT_AGAIN:
|
||||||
nxt_timer_add(task->thread->engine, &c->read_timer, 5000);
|
c->write_timer.handler = nxt_openssl_conn_io_shutdown_timeout;
|
||||||
|
nxt_timer_add(task->thread->engine, &c->write_timer, 5000);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -1237,6 +1240,23 @@ nxt_openssl_conn_test_error(nxt_task_t *task, nxt_conn_t *c, int ret,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
nxt_openssl_conn_io_shutdown_timeout(nxt_task_t *task, void *obj, void *data)
|
||||||
|
{
|
||||||
|
nxt_conn_t *c;
|
||||||
|
nxt_timer_t *timer;
|
||||||
|
|
||||||
|
timer = obj;
|
||||||
|
|
||||||
|
nxt_debug(task, "openssl conn shutdown timeout");
|
||||||
|
|
||||||
|
c = nxt_write_timer_conn(timer);
|
||||||
|
|
||||||
|
c->socket.timedout = 1;
|
||||||
|
nxt_openssl_conn_io_shutdown(task, c, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void nxt_cdecl
|
static void nxt_cdecl
|
||||||
nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, const char *fmt, ...)
|
nxt_openssl_conn_error(nxt_task_t *task, nxt_err_t err, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2477,6 +2477,7 @@ nxt_router_tls_rpc_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tlscf->no_wait_shutdown = 1;
|
||||||
rpc->socket_conf->tls = tlscf;
|
rpc->socket_conf->tls = tlscf;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ struct nxt_tls_conf_s {
|
|||||||
char *ca_certificate;
|
char *ca_certificate;
|
||||||
|
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
|
|
||||||
|
uint8_t no_wait_shutdown; /* 1 bit */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user