修正KNI接受模块在KNI重复注册时导致的double-free问题
This commit is contained in:
@@ -19,7 +19,7 @@
|
|||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
#ifndef TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT
|
#ifndef TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT
|
||||||
#define TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT "/var/run/.tfe_kni_acceptor_handler"
|
#define TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT "/var/run/.tfe_kni_acceptor_handler"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The KNI and TFE communicate with each other by UNIX-based socket,
|
/* The KNI and TFE communicate with each other by UNIX-based socket,
|
||||||
@@ -104,9 +104,17 @@ struct kni_acceptor
|
|||||||
|
|
||||||
void __kni_conn_close(struct kni_acceptor * ctx)
|
void __kni_conn_close(struct kni_acceptor * ctx)
|
||||||
{
|
{
|
||||||
if (ctx->fd_kni_conn != 0) close(ctx->fd_kni_conn);
|
if (ctx->fd_kni_conn != 0)
|
||||||
if (ctx->ev_kni_conn != NULL) event_free(ctx->ev_kni_conn);
|
{
|
||||||
if (ctx->pid_kni_conn != 0) ctx->pid_kni_conn = 0;
|
close(ctx->fd_kni_conn);
|
||||||
|
ctx->fd_kni_conn = 0;
|
||||||
|
}
|
||||||
|
if (ctx->ev_kni_conn != NULL)
|
||||||
|
{
|
||||||
|
event_free(ctx->ev_kni_conn);
|
||||||
|
ctx->ev_kni_conn = NULL;
|
||||||
|
}
|
||||||
|
if (ctx->pid_kni_conn != 0) { ctx->pid_kni_conn = 0; }
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
||||||
@@ -116,7 +124,7 @@ static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
|||||||
size_t __left_data_len = sz_data;
|
size_t __left_data_len = sz_data;
|
||||||
|
|
||||||
/* Parse the STREAM header */
|
/* Parse the STREAM header */
|
||||||
struct kni_tlv_header * tlv_header = (struct kni_tlv_header *)__cursor;
|
struct kni_tlv_header * tlv_header = (struct kni_tlv_header *) __cursor;
|
||||||
if (__left_data_len < sizeof(struct kni_tlv_header))
|
if (__left_data_len < sizeof(struct kni_tlv_header))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(ctx->logger, "Invalid KNI TLV header format, length is not enough.");
|
TFE_LOG_ERROR(ctx->logger, "Invalid KNI TLV header format, length is not enough.");
|
||||||
@@ -135,7 +143,7 @@ static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
|||||||
__left_data_len -= sizeof(struct kni_tlv_header);
|
__left_data_len -= sizeof(struct kni_tlv_header);
|
||||||
__cursor += sizeof(struct kni_tlv_header);
|
__cursor += sizeof(struct kni_tlv_header);
|
||||||
|
|
||||||
for(unsigned int iter_tlv_tuples = 0; iter_tlv_tuples < nr_tlv_tuples; iter_tlv_tuples++)
|
for (unsigned int iter_tlv_tuples = 0; iter_tlv_tuples < nr_tlv_tuples; iter_tlv_tuples++)
|
||||||
{
|
{
|
||||||
struct kni_tlv_info * tlv_info = (struct kni_tlv_info *) __cursor;
|
struct kni_tlv_info * tlv_info = (struct kni_tlv_info *) __cursor;
|
||||||
size_t sz_tlv_info = tlv_info->len + sizeof(struct kni_tlv_info);
|
size_t sz_tlv_info = tlv_info->len + sizeof(struct kni_tlv_info);
|
||||||
@@ -151,8 +159,8 @@ static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
|||||||
/* VALUE is uint32_t, length is 4 */
|
/* VALUE is uint32_t, length is 4 */
|
||||||
case KNI_TLV_TYPE_PROTOCOL:
|
case KNI_TLV_TYPE_PROTOCOL:
|
||||||
{
|
{
|
||||||
uint32_t __value = *(uint32_t *)(tlv_info->value);
|
uint32_t __value = *(uint32_t *) (tlv_info->value);
|
||||||
if(__value == KNI_TLV_VALUE_HTTP)
|
if (__value == KNI_TLV_VALUE_HTTP)
|
||||||
{
|
{
|
||||||
out_para->session_type = STREAM_PROTO_PLAIN;
|
out_para->session_type = STREAM_PROTO_PLAIN;
|
||||||
}
|
}
|
||||||
@@ -164,10 +172,10 @@ static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* VALUE is uint32_t, length is 4 */
|
/* VALUE is uint32_t, length is 4 */
|
||||||
case KNI_TLV_TYPE_KEYRING_ID:
|
case KNI_TLV_TYPE_KEYRING_ID:
|
||||||
{
|
{
|
||||||
uint32_t __value = *(uint32_t *)(tlv_info->value);
|
uint32_t __value = *(uint32_t *) (tlv_info->value);
|
||||||
out_para->keyring_id = __value;
|
out_para->keyring_id = __value;
|
||||||
assert(tlv_info->len == sizeof(uint32_t));
|
assert(tlv_info->len == sizeof(uint32_t));
|
||||||
break;
|
break;
|
||||||
@@ -185,7 +193,7 @@ static int __kni_parse_tlv_data(struct kni_acceptor * ctx,
|
|||||||
|
|
||||||
void __kni_event_cb(evutil_socket_t fd, short what, void * user)
|
void __kni_event_cb(evutil_socket_t fd, short what, void * user)
|
||||||
{
|
{
|
||||||
struct kni_acceptor * __ctx = (struct kni_acceptor *)user;
|
struct kni_acceptor * __ctx = (struct kni_acceptor *) user;
|
||||||
struct cmsghdr * __cmsghdr;
|
struct cmsghdr * __cmsghdr;
|
||||||
struct tfe_proxy_accept_para __accept_para{};
|
struct tfe_proxy_accept_para __accept_para{};
|
||||||
|
|
||||||
@@ -214,8 +222,8 @@ void __kni_event_cb(evutil_socket_t fd, short what, void * user)
|
|||||||
__msghdr.msg_iovlen = 1;
|
__msghdr.msg_iovlen = 1;
|
||||||
__msghdr.msg_name = NULL;
|
__msghdr.msg_name = NULL;
|
||||||
__msghdr.msg_namelen = 0;
|
__msghdr.msg_namelen = 0;
|
||||||
__msghdr.msg_control = (void *)(__cmptr);
|
__msghdr.msg_control = (void *) (__cmptr);
|
||||||
__msghdr.msg_controllen = (size_t)__CONTROLLEN;
|
__msghdr.msg_controllen = (size_t) __CONTROLLEN;
|
||||||
|
|
||||||
ssize_t rd = recvmsg(fd, &__msghdr, 0);
|
ssize_t rd = recvmsg(fd, &__msghdr, 0);
|
||||||
if (rd == -1 && (errno == EINTR || errno == EAGAIN))
|
if (rd == -1 && (errno == EINTR || errno == EAGAIN))
|
||||||
@@ -229,7 +237,7 @@ void __kni_event_cb(evutil_socket_t fd, short what, void * user)
|
|||||||
}
|
}
|
||||||
else if (rd == 0)
|
else if (rd == 0)
|
||||||
{
|
{
|
||||||
TFE_LOG_INFO(__ctx->logger, "KNI connected from process %u. ", __ctx->pid_kni_conn);
|
TFE_LOG_INFO(__ctx->logger, "KNI disconnect (PID = %u). ", __ctx->pid_kni_conn);
|
||||||
goto __close_kni_connection;
|
goto __close_kni_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,7 +250,7 @@ void __kni_event_cb(evutil_socket_t fd, short what, void * user)
|
|||||||
goto __close_kni_connection;
|
goto __close_kni_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unlikely(__kni_parse_tlv_data(__ctx, &__accept_para, __buffer, (size_t)rd) < 0))
|
if (unlikely(__kni_parse_tlv_data(__ctx, &__accept_para, __buffer, (size_t) rd) < 0))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, close KNI connection.");
|
TFE_LOG_ERROR(__ctx->logger, "Failed at parsing TLV format, close KNI connection.");
|
||||||
goto __close_kni_connection;
|
goto __close_kni_connection;
|
||||||
@@ -264,14 +272,14 @@ __close_kni_connection:
|
|||||||
|
|
||||||
__drop_recieved_fds:
|
__drop_recieved_fds:
|
||||||
TFE_PROXY_STAT_INCREASE(STAT_FD_CLOSE_BY_KNI_ACCEPT_FAIL, 2);
|
TFE_PROXY_STAT_INCREASE(STAT_FD_CLOSE_BY_KNI_ACCEPT_FAIL, 2);
|
||||||
evutil_closesocket(__fds[0]);
|
if (__fds != NULL) evutil_closesocket(__fds[0]);
|
||||||
evutil_closesocket(__fds[1]);
|
if (__fds != NULL) evutil_closesocket(__fds[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __kni_listener_accept_cb(struct evconnlistener * listener, evutil_socket_t fd,
|
void __kni_listener_accept_cb(struct evconnlistener * listener, evutil_socket_t fd,
|
||||||
struct sockaddr * sk_addr, int sk_len, void * user)
|
struct sockaddr * sk_addr, int sk_len, void * user)
|
||||||
{
|
{
|
||||||
struct kni_acceptor * __ctx = (struct kni_acceptor *)user;
|
struct kni_acceptor * __ctx = (struct kni_acceptor *) user;
|
||||||
struct event * __event = NULL;
|
struct event * __event = NULL;
|
||||||
|
|
||||||
struct ucred __cr{};
|
struct ucred __cr{};
|
||||||
@@ -287,21 +295,22 @@ void __kni_listener_accept_cb(struct evconnlistener * listener, evutil_socket_t
|
|||||||
if (unlikely(__ctx->ev_kni_conn != NULL))
|
if (unlikely(__ctx->ev_kni_conn != NULL))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "One KNI(PID = %d) has been connected to our program, "
|
TFE_LOG_ERROR(__ctx->logger, "One KNI(PID = %d) has been connected to our program, "
|
||||||
"close this connection", __ctx->pid_kni_conn);
|
"close this connection", __ctx->pid_kni_conn);
|
||||||
goto __close_this_connection;
|
evutil_closesocket(fd);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get Peer's PID */
|
/* Get Peer's PID */
|
||||||
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *)&__cr, &__cr_len) < 0)
|
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void *) &__cr, &__cr_len) < 0)
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at getsockopt(SO_PEERCRED) for fd %d, close this connection");
|
TFE_LOG_ERROR(__ctx->logger, "Failed at getsockopt(SO_PEERCRED) for fd %d, close this connection", fd);
|
||||||
goto __close_this_connection;
|
goto __close_this_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
__event = event_new(__ctx->ev_base, fd, EV_READ | EV_PERSIST, __kni_event_cb, __ctx);
|
__event = event_new(__ctx->ev_base, fd, EV_READ | EV_PERSIST, __kni_event_cb, __ctx);
|
||||||
if (unlikely(__event == NULL))
|
if (unlikely(__event == NULL))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at creating event, close this connection.");
|
TFE_LOG_ERROR(__ctx->logger, "Failed at creating event for fd %d, close this connection.", fd);
|
||||||
goto __close_this_connection;
|
goto __close_this_connection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,7 +325,7 @@ void __kni_listener_accept_cb(struct evconnlistener * listener, evutil_socket_t
|
|||||||
__ctx->ev_kni_conn = __event;
|
__ctx->ev_kni_conn = __event;
|
||||||
__ctx->pid_kni_conn = __cr.pid;
|
__ctx->pid_kni_conn = __cr.pid;
|
||||||
|
|
||||||
TFE_LOG_INFO(__ctx->logger, "KNI connected from process %u", __ctx->pid_kni_conn);
|
TFE_LOG_INFO(__ctx->logger, "KNI connected (PID = %u, fd = %d). ", __ctx->pid_kni_conn, __ctx->fd_kni_conn);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
__close_this_connection:
|
__close_this_connection:
|
||||||
@@ -325,16 +334,16 @@ __close_this_connection:
|
|||||||
|
|
||||||
void * __kni_listener_thread_entry(void * args)
|
void * __kni_listener_thread_entry(void * args)
|
||||||
{
|
{
|
||||||
struct kni_acceptor * __ctx = (struct kni_acceptor *)args;
|
struct kni_acceptor * __ctx = (struct kni_acceptor *) args;
|
||||||
assert(__ctx != NULL && __ctx->thread == pthread_self());
|
assert(__ctx != NULL && __ctx->thread == pthread_self());
|
||||||
|
|
||||||
TFE_LOG_DEBUG(__ctx->logger, "Starting KNI listener thread...");
|
TFE_LOG_DEBUG(__ctx->logger, "Starting KNI listener thread...");
|
||||||
event_base_dispatch(__ctx->ev_base);
|
event_base_dispatch(__ctx->ev_base);
|
||||||
TFE_LOG_DEBUG(__ctx->logger, "Stoping KNI listener thread...");
|
TFE_LOG_DEBUG(__ctx->logger, "Stoping KNI listener thread...");
|
||||||
return (void *)NULL;
|
return (void *) NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void kni_acceptor_deinit(struct kni_acceptor *ctx)
|
void kni_acceptor_deinit(struct kni_acceptor * ctx)
|
||||||
{
|
{
|
||||||
if (ctx != NULL && ctx->ev_listener != NULL)
|
if (ctx != NULL && ctx->ev_listener != NULL)
|
||||||
{
|
{
|
||||||
@@ -359,7 +368,7 @@ void kni_acceptor_deinit(struct kni_acceptor *ctx)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kni_acceptor * kni_acceptor_init(struct tfe_proxy *proxy, const char *profile, void *logger)
|
struct kni_acceptor * kni_acceptor_init(struct tfe_proxy * proxy, const char * profile, void * logger)
|
||||||
{
|
{
|
||||||
struct kni_acceptor * __ctx = ALLOC(struct kni_acceptor, 1);
|
struct kni_acceptor * __ctx = ALLOC(struct kni_acceptor, 1);
|
||||||
struct sockaddr_un __sockaddr_un;
|
struct sockaddr_un __sockaddr_un;
|
||||||
@@ -371,12 +380,13 @@ struct kni_acceptor * kni_acceptor_init(struct tfe_proxy *proxy, const char *pro
|
|||||||
|
|
||||||
/* Read the unix domain socket file, this file is used to recieve fds from KNI */
|
/* Read the unix domain socket file, this file is used to recieve fds from KNI */
|
||||||
MESA_load_profile_string_def(profile, "kni", "uxdomain", __ctx->str_unixdomain_file,
|
MESA_load_profile_string_def(profile, "kni", "uxdomain", __ctx->str_unixdomain_file,
|
||||||
sizeof(__ctx->str_unixdomain_file), TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT);
|
sizeof(__ctx->str_unixdomain_file), TFE_CONFIG_KNI_UXDOMAIN_PATH_DEFAULT);
|
||||||
|
|
||||||
if (unlikely(unlink(__ctx->str_unixdomain_file) < 0))
|
if (unlikely(unlink(__ctx->str_unixdomain_file) < 0))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at unlink undomain file %s: %s",
|
TFE_LOG_ERROR(__ctx->logger, "Failed at unlink undomain file %s: %s",
|
||||||
__ctx->str_unixdomain_file, strerror(errno)); goto __errout;
|
__ctx->str_unixdomain_file, strerror(errno));
|
||||||
|
goto __errout;
|
||||||
}
|
}
|
||||||
|
|
||||||
__sockaddr_un.sun_family = AF_UNIX;
|
__sockaddr_un.sun_family = AF_UNIX;
|
||||||
@@ -392,7 +402,7 @@ struct kni_acceptor * kni_acceptor_init(struct tfe_proxy *proxy, const char *pro
|
|||||||
|
|
||||||
/* Create a listener */
|
/* Create a listener */
|
||||||
__ctx->ev_listener = evconnlistener_new_bind(__ctx->ev_base, __kni_listener_accept_cb, __ctx, 0,
|
__ctx->ev_listener = evconnlistener_new_bind(__ctx->ev_base, __kni_listener_accept_cb, __ctx, 0,
|
||||||
TFE_CONFIG_BACKLOG_DEFAULT, (struct sockaddr *)(&__sockaddr_un), sizeof(__sockaddr_un));
|
TFE_CONFIG_BACKLOG_DEFAULT, (struct sockaddr *) (&__sockaddr_un), sizeof(__sockaddr_un));
|
||||||
|
|
||||||
if (unlikely(__ctx->ev_listener == NULL))
|
if (unlikely(__ctx->ev_listener == NULL))
|
||||||
{
|
{
|
||||||
@@ -401,7 +411,7 @@ struct kni_acceptor * kni_acceptor_init(struct tfe_proxy *proxy, const char *pro
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Create a thread to dispatch ctx->evbase */
|
/* Create a thread to dispatch ctx->evbase */
|
||||||
ret = pthread_create(&__ctx->thread, NULL, __kni_listener_thread_entry, (void *)__ctx);
|
ret = pthread_create(&__ctx->thread, NULL, __kni_listener_thread_entry, (void *) __ctx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(__ctx->logger, "Failed at creating listener thread: %s", strerror(errno));
|
TFE_LOG_ERROR(__ctx->logger, "Failed at creating listener thread: %s", strerror(errno));
|
||||||
|
|||||||
@@ -300,7 +300,13 @@ int main(int argc, char * argv[])
|
|||||||
{
|
{
|
||||||
const char * main_profile = "./conf/tfe.conf";
|
const char * main_profile = "./conf/tfe.conf";
|
||||||
|
|
||||||
g_default_logger = MESA_create_runtime_log_handle("log/tfe.log", RLOG_LV_DEBUG);
|
unsigned int __log_level = RLOG_LV_INFO;
|
||||||
|
MESA_load_profile_uint_def(main_profile, "log", "level", &__log_level, RLOG_LV_INFO);
|
||||||
|
|
||||||
|
char __log_path[TFE_STRING_MAX]= {};
|
||||||
|
MESA_load_profile_string_def(main_profile, "log", "location", __log_path, sizeof(__log_path), "log/tfe.log");
|
||||||
|
|
||||||
|
g_default_logger = MESA_create_runtime_log_handle(__log_path, __log_level);
|
||||||
if (unlikely(g_default_logger == NULL))
|
if (unlikely(g_default_logger == NULL))
|
||||||
{
|
{
|
||||||
TFE_LOG_ERROR(g_default_logger, "Failed at creating default logger: %s", "log/tfe.log");
|
TFE_LOG_ERROR(g_default_logger, "Failed at creating default logger: %s", "log/tfe.log");
|
||||||
|
|||||||
Reference in New Issue
Block a user