Fix socket fd leak 50/69250/3 accepted/tizen/ivi/20160513.082347 accepted/tizen/mobile/20160513.082336 accepted/tizen/tv/20160513.082342 accepted/tizen/wearable/20160513.082332 submit/tizen/20160513.050341
authorHyunho Kang <hhstark.kang@samsung.com>
Thu, 12 May 2016 09:17:17 +0000 (18:17 +0900)
committerHyunho Kang <hhstark.kang@samsung.com>
Thu, 12 May 2016 11:07:28 +0000 (20:07 +0900)
Uneccessary socket dup and send uneccessary fd using gdbus cause fd leak
It also cause sender didn't clear invalid opponent info which already
die.

Change-Id: Ifa79b3340ab5358ecfb1deb5791dc1d5df35ac5f
Signed-off-by: Hyunho Kang <hhstark.kang@samsung.com>
src/message-port.c

index a337d29..fb1163a 100755 (executable)
@@ -51,6 +51,9 @@
 #define DBUS_RELEASE_NAME_REPLY_NOT_OWNER       3 /* *< Service is not an owner of the given name */
 #define HEADER_LEN 8
 #define MAX_RETRY_CNT 2
+#define SOCK_PAIR_SENDER 0
+#define SOCK_PAIR_RECEIVER 1
+
 
 #define retvm_if(expr, val, fmt, arg...) do { \
        if (expr) { \
@@ -124,7 +127,7 @@ typedef struct port_list_info {
        char *port_name;
        char *encoded_bus_name;
        bool is_trusted;
-       int sock_pair[2];
+       int send_sock_fd;
        int watcher_id;
        bool exist;
 } port_list_info_s;
@@ -297,6 +300,11 @@ static void on_name_vanished(GDBusConnection *connection,
        port_list_info_s *pli = (port_list_info_s *)user_data;
        g_bus_unwatch_name(pli->watcher_id);
        pli->exist = false;
+       _LOGI("name vanished socket : %d", pli->send_sock_fd);
+       if (pli->send_sock_fd > 0) {
+               close(pli->send_sock_fd);
+               pli->send_sock_fd = 0;
+       }
 }
 
 static int __get_local_port_info(int id, message_port_local_port_info_s **info)
@@ -325,16 +333,12 @@ static port_list_info_s *__set_remote_port_info(const char *remote_app_id, const
                goto out;
        }
        port_info->is_trusted = is_trusted;
-
        port_info->encoded_bus_name = __get_encoded_name(remote_app_id, remote_port, is_trusted);
        if (port_info->encoded_bus_name == NULL) {
                ret_val = MESSAGEPORT_ERROR_OUT_OF_MEMORY;
                goto out;
        }
-
-       port_info->sock_pair[0] = 0;
-       port_info->sock_pair[1] = 0;
-
+       port_info->send_sock_fd = 0;
 out:
        if (ret_val != MESSAGEPORT_ERROR_NONE) {
                if (port_info) {
@@ -715,6 +719,11 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
        message_port_callback_info_s *callback_info;
        int local_reg_id = 0;
        char buf[1024];
+       GDBusMessage *msg;
+       GUnixFDList *fd_list;
+       int fd_len;
+       int *returned_fds;
+       int fd;
 
        g_variant_get(parameters, "(ssbbssbus)", &local_appid, &local_port, &local_trusted, &bi_dir,
                        &remote_appid, &remote_port, &remote_trusted, &len, &raw);
@@ -775,18 +784,12 @@ static bool send_message(GVariant *parameters, GDBusMethodInvocation *invocation
        callback_info->remote_app_id = strdup(local_appid);
        callback_info->callback = mi->callback;
 
-       GError *error = NULL;
-       GDBusMessage *msg = g_dbus_method_invocation_get_message(invocation);
-
-       GUnixFDList *fd_list = g_dbus_message_get_unix_fd_list(msg);
-       int fd = g_unix_fd_list_get(fd_list, 0, &error);
-       if (error) {
-               LOGE("g_unix_fd_list_get fail : %s", error->message);
-               g_error_free(error);
-       }
-
-       LOGI("g_unix_fd_list_get fd: [%d]", fd);
+       msg = g_dbus_method_invocation_get_message(invocation);
+       fd_list = g_dbus_message_get_unix_fd_list(msg);
+       returned_fds = g_unix_fd_list_steal_fds(fd_list, &fd_len);
+       fd = returned_fds[0];
 
+       LOGI("g_unix_fd_list_get %d fd: [%d]", fd_len, fd);
        if (fd > 0) {
 
                callback_info->gio_read = g_io_channel_unix_new(fd);
@@ -1296,6 +1299,7 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
        GDBusMessage *msg = NULL;
        GError *err = NULL;
        GVariant *body = NULL;
+       int sock_pair[2] = {0,};
 
        ret = __get_remote_port_info(remote_appid, remote_port, trusted_message, &remote_app_info, &port_info);
        if (ret != MESSAGEPORT_ERROR_NONE)
@@ -1313,8 +1317,8 @@ 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,
+       if (port_info->send_sock_fd > 0) {
+               ret = __message_port_send_async(port_info->send_sock_fd, message,
                                (local_port) ? local_port : "", local_trusted, bi_dir);
        } else {
 
@@ -1333,29 +1337,26 @@ static int __message_port_send_message(const char *remote_appid, const char *rem
 
                body = g_variant_new("(ssbbssbus)", __app_id, (local_port) ? local_port : "", local_trusted, bi_dir,
                                remote_appid, remote_port, trusted_message, len, raw);
-
-
                if (strcmp(remote_appid, __app_id) != 0) { /* self send */
 
                        /*  if message-port fail to get socket pair, communicate using GDBus */
-                       if (aul_request_message_port_socket_pair(port_info->sock_pair) != AUL_R_OK) {
+                       if (aul_request_message_port_socket_pair(sock_pair) != AUL_R_OK) {
                                _LOGE("error create socket pair");
                        } else {
 
-                               _LOGI("sock pair : %d, %d", port_info->sock_pair[0], port_info->sock_pair[1]);
-
+                               _LOGI("sock pair : %d, %d",
+                                               sock_pair[SOCK_PAIR_SENDER], sock_pair[SOCK_PAIR_RECEIVER]);
                                fd_list = g_unix_fd_list_new();
-                               g_unix_fd_list_append(fd_list, port_info->sock_pair[1], &err);
-                               g_unix_fd_list_append(fd_list, port_info->sock_pair[0], &err);
-
+                               g_unix_fd_list_append(fd_list, sock_pair[SOCK_PAIR_RECEIVER], &err);
                                if (err != NULL) {
                                        _LOGE("g_unix_fd_list_append [%s]", error->message);
                                        ret = MESSAGEPORT_ERROR_IO_ERROR;
                                        g_error_free(err);
                                        goto out;
                                }
+                               port_info->send_sock_fd = sock_pair[SOCK_PAIR_SENDER];
+                               close(sock_pair[SOCK_PAIR_RECEIVER]);
                        }
-
                }
 
                msg = g_dbus_message_new_method_call(bus_name, MESSAGEPORT_OBJECT_PATH, interface_name, "send_message");