From 0f0ec1bc41366ca18e31855226415ba14bee589f Mon Sep 17 00:00:00 2001 From: Hyunho Kang Date: Mon, 11 Jan 2016 19:26:12 +0900 Subject: [PATCH] Fix message_port_send_message_with_local_port NULL port name bug Because of this bug, user can not receive remote app's port name when user send message with message_port_send_message_with_local_port right after message_port_send_message API call. Change-Id: Ic04fc05216e08ee0fc7a252c72ca3a23678d000e Signed-off-by: Hyunho Kang --- src/message-port.c | 242 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 154 insertions(+), 88 deletions(-) diff --git a/src/message-port.c b/src/message-port.c index b6b5a2a..b5a0364 100755 --- a/src/message-port.c +++ b/src/message-port.c @@ -91,17 +91,18 @@ enum __certificate_info_type { }; typedef struct message_port_pkt { - int len; + int remote_port_name_len; + char *remote_port_name; bool is_bidirection; - unsigned char data[1]; + int data_len; + unsigned char *data; } message_port_pkt_s; typedef struct message_port_callback_info { messageport_message_cb callback; + bool is_trusted; int local_id; char *remote_app_id; - char *remote_port; - bool is_trusted; GIOChannel *gio_read; int g_src_id; } message_port_callback_info_s; @@ -138,9 +139,6 @@ static void __callback_info_free(message_port_callback_info_s *callback_info) if (callback_info->remote_app_id) free(callback_info->remote_app_id); - if (callback_info->remote_port) - free(callback_info->remote_port); - if (callback_info->gio_read != NULL) { g_io_channel_shutdown(callback_info->gio_read, FALSE, &error); if (error) { @@ -493,45 +491,137 @@ out: return pid; } +static int __write_socket(int fd, + const char *buffer, + unsigned int nbytes, + unsigned int *bytes_write) +{ + unsigned int left = nbytes; + ssize_t nb; + int retry_cnt = 0; + + *bytes_write = 0; + while (left && (retry_cnt < MAX_RETRY_CNT)) { + nb = write(fd, buffer, left); + if (nb == -1) { + if (errno == EINTR) { + LOGE("__write_socket: EINTR error continue ..."); + retry_cnt++; + continue; + } + LOGE("__write_socket: ...error fd %d: errno %d\n", fd, errno); + return MESSAGEPORT_ERROR_IO_ERROR; + } + + left -= nb; + buffer += nb; + *bytes_write += nb; + retry_cnt = 0; + } + return MESSAGEPORT_ERROR_NONE; +} + +static int __write_string_to_socket(int fd, const char *buffer, int string_len) +{ + unsigned int nb; + if (__write_socket(fd, (char *)&string_len, sizeof(string_len), &nb) != MESSAGEPORT_ERROR_NONE) { + _LOGE("write string_len fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + + if (string_len > 0) { + if (__write_socket(fd, buffer, string_len, &nb) != MESSAGEPORT_ERROR_NONE) { + _LOGE("wirte buffer fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + } + return MESSAGEPORT_ERROR_NONE; +} + +static int __read_socket(int fd, + char *buffer, + unsigned int nbytes, + unsigned int *bytes_read) +{ + unsigned int left = nbytes; + ssize_t nb; + int retry_cnt = 0; + + *bytes_read = 0; + while (left && (retry_cnt < MAX_RETRY_CNT)) { + nb = read(fd, buffer, left); + if (nb == 0) { + LOGE("__read_socket: ...read EOF, socket closed %d: nb %d\n", fd, nb); + return MESSAGEPORT_ERROR_IO_ERROR; + } else if (nb == -1) { + if (errno == EINTR) { + LOGE("__read_socket: EINTR error continue ..."); + retry_cnt++; + continue; + } + LOGE("__read_socket: ...error fd %d: errno %d\n", fd, errno); + return MESSAGEPORT_ERROR_IO_ERROR; + } + + left -= nb; + buffer += nb; + *bytes_read += nb; + retry_cnt = 0; + } + return MESSAGEPORT_ERROR_NONE; +} + +static int __read_string_from_socket(int fd, char **buffer, int *string_len) +{ + unsigned int nb; + if (__read_socket(fd, (char *)string_len, sizeof(*string_len), &nb) != MESSAGEPORT_ERROR_NONE) { + LOGE("read socket fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + if (*string_len > 0) { + *buffer = (char *)calloc(*string_len, sizeof(char)); + if (*buffer == NULL) { + LOGE("Out of memory."); + return MESSAGEPORT_ERROR_IO_ERROR; + } + if (__read_socket(fd, *buffer, *string_len, &nb) != MESSAGEPORT_ERROR_NONE) { + LOGE("read socket fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + } + return MESSAGEPORT_ERROR_NONE; +} + message_port_pkt_s *__message_port_recv_raw(int fd) { - int len; - int ret; message_port_pkt_s *pkt = NULL; + unsigned int nb; - pkt = (message_port_pkt_s *)calloc(sizeof(char) * MAX_MESSAGE_SIZE, 1); + pkt = (message_port_pkt_s *)calloc(sizeof(message_port_pkt_s), 1); if (pkt == NULL) { close(fd); return NULL; } - -retry_recv: - /* receive single packet from socket */ - len = recv(fd, pkt, MAX_MESSAGE_SIZE, 0); - if (len < 0) { - _LOGE("recv error: %d[%s]", errno, strerror(errno)); - if (errno == EINTR) - goto retry_recv; + if (__read_string_from_socket(fd, (char **)&pkt->remote_port_name, &pkt->remote_port_name_len) != MESSAGEPORT_ERROR_NONE) { + LOGE("read socket fail: port_name"); + free(pkt->remote_port_name); + free(pkt); + close(fd); + return NULL; } - - if (len < HEADER_LEN) { - _LOGE("recv error %d %d", len, pkt->len); + if (__read_socket(fd, (char *)&pkt->is_bidirection, sizeof(pkt->is_bidirection), &nb) != MESSAGEPORT_ERROR_NONE) { + LOGE("read socket fail: is_bidirection"); + free(pkt->remote_port_name); free(pkt); close(fd); return NULL; } - while (len < (pkt->len + HEADER_LEN)) { -retry_recv1: - ret = recv(fd, &pkt->data[len - 8], MAX_MESSAGE_SIZE, 0); - if (ret < 0) { - SECURE_LOGE("recv error: %d %d %d", errno, len, pkt->len); - if (errno == EINTR) - goto retry_recv1; - free(pkt); - close(fd); - return NULL; - } - len += ret; + if (__read_string_from_socket(fd, (char **)&pkt->data, &pkt->data_len) != MESSAGEPORT_ERROR_NONE) { + LOGE("read socket fail: data"); + free(pkt->remote_port_name); + free(pkt); + close(fd); + return NULL; } return pkt; } @@ -544,7 +634,6 @@ static gboolean __socket_request_handler(GIOChannel *gio, message_port_callback_info_s *mi; message_port_pkt_s *pkt; bundle *kb = NULL; - bool is_bidirection; GError *error = NULL; mi = (message_port_callback_info_s *)data; @@ -579,16 +668,20 @@ static gboolean __socket_request_handler(GIOChannel *gio, return FALSE; } - kb = bundle_decode(pkt->data, pkt->len); - is_bidirection = pkt->is_bidirection; + kb = bundle_decode(pkt->data, pkt->data_len); - if (is_bidirection) - mi->callback(mi->local_id, mi->remote_app_id, mi->remote_port, mi->is_trusted, kb, NULL); + if (pkt->is_bidirection) + mi->callback(mi->local_id, mi->remote_app_id, pkt->remote_port_name, mi->is_trusted, kb, NULL); else mi->callback(mi->local_id, mi->remote_app_id, NULL, mi->is_trusted, kb, NULL); - if (pkt) + if (pkt) { + if (pkt->remote_port_name) + free(pkt->remote_port_name); + if (pkt->data) + free(pkt->data); free(pkt); + } } return TRUE; @@ -668,9 +761,8 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation callback_info->local_id = mi->local_id; callback_info->remote_app_id = strdup(local_appid); - callback_info->remote_port = strdup(local_port); - callback_info->is_trusted = local_trusted; callback_info->callback = mi->callback; + callback_info->is_trusted = local_trusted; GError *error = NULL; GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation); @@ -1124,70 +1216,44 @@ static int __register_message_port(const char *local_port, bool is_trusted, mess return local_id; } -int __message_port_send_async(int sockfd, bundle *kb, const char *app_id, const char *local_port, +int __message_port_send_async(int sockfd, bundle *kb, const char *local_port, bool local_trusted, bool is_bidirection) { - - int len; int ret = 0; - message_port_pkt_s *pkt = NULL; - int pkt_size; - - int datalen; + int data_len; + int local_port_len = 0; + unsigned int nb; bundle_raw *kb_data = NULL; - bundle_encode(kb, &kb_data, &datalen); + if (local_port != NULL) + local_port_len = strlen(local_port) + 1; + + if (__write_string_to_socket(sockfd, local_port, local_port_len) != MESSAGEPORT_ERROR_NONE) { + _LOGE("write local_port fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + if (__write_socket(sockfd, (char *)&is_bidirection, sizeof(is_bidirection), &nb) != MESSAGEPORT_ERROR_NONE) { + _LOGE("write is_bidirection fail"); + return MESSAGEPORT_ERROR_IO_ERROR; + } + + bundle_encode(kb, &kb_data, &data_len); if (kb_data == NULL) { _LOGE("bundle encode fail"); ret = MESSAGEPORT_ERROR_IO_ERROR; goto out; } - - if (datalen > MAX_MESSAGE_SIZE - HEADER_LEN) { + if (data_len > MAX_MESSAGE_SIZE) { _LOGE("bigger than max size\n"); ret = MESSAGEPORT_ERROR_MAX_EXCEEDED; goto out; } - pkt_size = datalen + 9; - pkt = (message_port_pkt_s *) malloc(sizeof(char) * pkt_size); - - if (NULL == pkt) { - _LOGE("Malloc Failed!"); - ret = MESSAGEPORT_ERROR_OUT_OF_MEMORY; - goto out; - } - memset(pkt, 0, pkt_size); - - pkt->len = datalen; - pkt->is_bidirection = is_bidirection; - - memcpy(pkt->data, kb_data, datalen); - - int retry_ctr = MAX_RETRY_CNT; - -retry_send: - if ((len = send(sockfd, pkt, pkt_size, 0)) != pkt_size) { - SECURE_LOGE("send() failed - len[%d] pkt_size[%d] (errno %d[%s])", len, pkt_size, - errno, strerror(errno)); - if (errno == EPIPE) - _LOGE("fd:%d\n", sockfd); - - if (errno == EINTR) { - if (retry_ctr > 0) { - _LOGI("Retrying send on fd[%d]", sockfd); - usleep(30 * 1000); - - retry_ctr--; - goto retry_send; - } - } + if (__write_string_to_socket(sockfd, (void *)kb_data, data_len) != MESSAGEPORT_ERROR_NONE) { + _LOGE("write kb_data fail"); ret = MESSAGEPORT_ERROR_IO_ERROR; - goto out; } out: - if (pkt) - free(pkt); if (kb_data) free(kb_data); @@ -1231,7 +1297,7 @@ static int __message_port_send_message(const char *remote_appid, const char *rem if (port_info->sock_pair[0] > 0) { ret = __message_port_send_async(port_info->sock_pair[0], message, - __app_id, (local_port) ? local_port : "", local_trusted, bi_dir); + (local_port) ? local_port : "", local_trusted, bi_dir); } else { bus_name = port_info->encoded_bus_name; -- 2.7.4