修正当进程句柄限制不足时,存在的随机关闭FD的问题并调整SSL关闭时的fd处理位置。

* 原实现在接收fd时,没有考虑可能只接收1个fd的情况。导致程序在接收1个fd时按2个fd处理,越界访问随机关闭fd。
* 现修正,接收2个一下fd时,关闭接收的fd。
* 同时调整SSL连接的FD关闭位置,改为在conn_private销毁时统一关闭,不在ssl部分关闭。
This commit is contained in:
luqiuwen
2019-09-05 16:16:51 +08:00
parent c9d814e17b
commit 611d978b91
4 changed files with 35 additions and 17 deletions

View File

@@ -42,7 +42,7 @@ void ssl_async_downstream_create(struct future * f, struct ssl_mgr * mgr, struct
evutil_socket_t fd_downstream, struct tfe_stream* tcp_stream);
void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev);
void ssl_stream_free(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev);
const char* ssl_stream_dump_info(struct ssl_stream *stream, char* buffer, size_t sz);
//Follow functions are allowed to call during runtime.
int ssl_manager_add_trust_ca(struct ssl_mgr* mgr, const char* pem_file);

View File

@@ -47,6 +47,8 @@ void acceptor_kni_v2_event(evutil_socket_t fd, short what, void * user)
struct tfe_cmsg * cmsg = NULL;
int * __fds = NULL;
unsigned int __nr_fds = 0;
assert(__ctx != NULL && __ctx->thread == pthread_self());
assert(what & EV_READ);
@@ -91,11 +93,19 @@ void acceptor_kni_v2_event(evutil_socket_t fd, short what, void * user)
TFE_LOG_ERROR(__ctx->logger, "failed at fetch CMSG_FIRSTHDR() from incoming fds.");
goto __drop_recieved_fds;
}
__fds = (int *) (CMSG_DATA(__cmsghdr));
if (unlikely(__fds == NULL))
switch(__cmsghdr->cmsg_len)
{
TFE_LOG_ERROR(__ctx->logger, "failed at fetch CMSG_DATA() from incoming fds.");
case CMSG_LEN(0 * sizeof(int)): { __nr_fds = 0; break;}
case CMSG_LEN(1 * sizeof(int)): { __nr_fds = 1; break;}
case CMSG_LEN(2 * sizeof(int)): { __nr_fds = 2; break; }
default: assert(0);
}
__fds = (int *) (CMSG_DATA(__cmsghdr));
if (unlikely(__fds == NULL || __nr_fds < 2))
{
TFE_LOG_ERROR(__ctx->logger, "No available file descriptors, drop the incoming fds.");
goto __drop_recieved_fds;
}
@@ -120,9 +130,13 @@ __die:
return;
__drop_recieved_fds:
TFE_PROXY_STAT_INCREASE(STAT_FD_CLOSE_BY_KNI_ACCEPT_FAIL, 2);
if (__fds != NULL) evutil_closesocket(__fds[0]);
if (__fds != NULL) evutil_closesocket(__fds[1]);
TFE_PROXY_STAT_INCREASE(STAT_FD_CLOSE_BY_KNI_ACCEPT_FAIL, __nr_fds);
for (unsigned int i = 0; i < __nr_fds; i++)
{
evutil_closesocket(__fds[i]);
}
assert(__nr_fds <= 2);
}
void * acceptor_kni_v2_event_thread_entry(void * args)

View File

@@ -2121,7 +2121,7 @@ complete:
* Guarantees that SSL and the corresponding SSL_CTX are freed and the
* socket is closed, eventually, or in the case of fatal errors, immediately.
*/
void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev)
void ssl_stream_free(struct ssl_stream * s_stream, struct event_base * evbase, struct bufferevent * bev)
{
UNUSED struct ssl_shutdown_ctx * sslshutctx = NULL;
evutil_socket_t fd=-1;
@@ -2165,8 +2165,8 @@ void ssl_stream_free_and_close_fd(struct ssl_stream * s_stream, struct event_bas
bufferevent_setcb(ubev, NULL, NULL, NULL, NULL);
bufferevent_free(ubev);
}
ssl_stream_free(s_stream);
evutil_closesocket(fd);
}
int ssl_manager_add_trust_ca(struct ssl_mgr* mgr, const char* pem_file)

View File

@@ -401,7 +401,11 @@ evutil_socket_t __conn_private_release_fd(struct tfe_conn_private * conn)
static void __conn_private_destory(struct tfe_conn_private * conn)
{
bufferevent_disable(conn->bev, EV_READ | EV_WRITE);
if (conn->bev)
{
bufferevent_disable(conn->bev, EV_READ | EV_WRITE);
bufferevent_free(conn->bev);
}
if(conn->ratelimit_bucket)
{
@@ -409,10 +413,9 @@ static void __conn_private_destory(struct tfe_conn_private * conn)
conn->ratelimit_bucket = NULL;
}
bufferevent_free(conn->bev);
if (conn->fd > 0)
{
evutil_closesocket(conn->fd);
assert(evutil_closesocket(conn->fd) >= 0);
}
free(conn);
@@ -423,8 +426,7 @@ static void __conn_private_destory_with_ssl(struct event_base * ev_base,
struct tfe_conn_private * conn, struct ssl_stream * ssl_stream)
{
if (ssl_stream == NULL) return __conn_private_destory(conn);
ssl_stream_free_and_close_fd(ssl_stream, ev_base, conn->bev);
conn->fd = -1;
ssl_stream_free(ssl_stream, ev_base, conn->bev);
return __conn_private_destory(conn);
}
@@ -1125,21 +1127,23 @@ void tfe_stream_destory(struct tfe_stream_private * stream)
if (__is_ssl(stream) && stream->ssl_upstream)
{
ssl_stream_free_and_close_fd(stream->ssl_upstream, ev_base, stream->conn_upstream->bev);
ssl_stream_free(stream->ssl_upstream, ev_base, stream->conn_upstream->bev);
}
if (__is_ssl(stream) && stream->ssl_downstream)
{
ssl_stream_free_and_close_fd(stream->ssl_downstream, ev_base, stream->conn_downstream->bev);
ssl_stream_free(stream->ssl_downstream, ev_base, stream->conn_downstream->bev);
}
if (stream->conn_upstream)
{
assert(stream->defer_fd_upstream <= 0);
__conn_private_destory(stream->conn_upstream);
}
if (stream->conn_downstream)
{
assert(stream->defer_fd_downstream <= 0);
__conn_private_destory(stream->conn_downstream);
}