修正KNI接受模块在KNI重复注册时导致的double-free问题

This commit is contained in:
Lu Qiuwen
2018-11-04 14:03:00 +08:00
parent b3b65369d8
commit 8962026092
2 changed files with 49 additions and 33 deletions

View File

@@ -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));

View File

@@ -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");