[ASAN] Fix heap-use-after-free (2) 14/202114/1
authorCheoleun Moon <chleun.moon@samsung.com>
Mon, 25 Mar 2019 00:57:20 +0000 (09:57 +0900)
committerCheoleun Moon <chleun.moon@samsung.com>
Mon, 25 Mar 2019 00:57:32 +0000 (09:57 +0900)
After a DNSServiceRef was released in dnssd_deregister_local_service(), it is
accessed in __dnssd_process_result(). It is because
a socket I/O event happened before the DNSServiceRef was released and as
a result __dnssd_process_result() was added to event loop.

Change-Id: I94d8bd45009b06ee63a52f726aaf8ce1a2cccf97
Signed-off-by: Cheoleun Moon <chleun.moon@samsung.com>
src/dns-sd/dns-sd-util.h
src/dns-sd/dns-sd.c

index 5a7c766f72452eeacc9c3f050373c8fad54aaab4..99c1f08721a8ff16d7dbbe205b7abc9f9ece4ad3 100644 (file)
@@ -105,7 +105,7 @@ typedef struct _dnssd_browse_data_s {
 
 typedef struct _dnssd_handle_s {
        DNSServiceRef sd_ref;
-       int watch_id;
+       guint watch_id;
        dnssd_type_e op_type;
        unsigned int service_handler;
        char *service_type;
@@ -117,7 +117,7 @@ typedef struct _dnssd_handle_s {
 typedef struct _resolve_reply_data {
        dnssd_handle_s *dnssd_handle;
        DNSServiceRef sd_ref;
-       int watch_id;
+       guint watch_id;
        char *service_name;
 } resolve_reply_data;
 
index 8f74d4a40eab95f6e80a5205ff29bc0bb694a2cd..f9d8f26228990613f8a308eb1132037790782712 100644 (file)
@@ -69,6 +69,47 @@ static const char *dnssd_error_to_string(dnssd_error_e error)
        }
 }
 
+static dnssd_handle_s *__dnssd_check_handle_validity(
+               dnssd_service_h dnssd_service)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       dnssd_handle_s *local_handle = NULL;
+       GSList *list;
+
+       for (list = dnssd_handle_list; list; list = list->next) {
+               local_handle = (dnssd_handle_s *)list->data;
+               if (local_handle && local_handle->service_handler ==
+                               dnssd_service) {
+                       DNSSD_LOGD("Service found with handler %u",
+                                       dnssd_service);
+                       __DNSSD_LOG_FUNC_EXIT__;
+                       return local_handle;
+               }
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return NULL;
+}
+
+static resolve_reply_data *__dnssd_check_resolve_reply_data_validity(
+               resolve_reply_data* data)
+{
+       __DNSSD_LOG_FUNC_ENTER__;
+       resolve_reply_data *local_data = NULL;
+       GSList *list;
+
+       for (list = resolve_handle_list; list; list = list->next) {
+               local_data = (resolve_reply_data*)list->data;
+               if (local_data == data) {
+                       __DNSSD_LOG_FUNC_EXIT__;
+                       return local_data;
+               }
+       }
+
+       __DNSSD_LOG_FUNC_EXIT__;
+       return NULL;
+}
+
 //LCOV_EXCL_START
 static bool __dnssd_check_permission()
 {
@@ -184,19 +225,18 @@ static int __dnssd_launch_mdns()
 //LCOV_EXCL_STOP
 
 //LCOV_EXCL_START
-static gboolean __dnssd_process_result(GIOChannel *source,
-               GIOCondition condition, gpointer data)
+static gboolean __dnssd_process_result(GIOCondition condition, DNSServiceRef sd_ref)
 {
-       DNSServiceRef *client = data;
        DNSServiceErrorType err;
 
-       (void)source;        //Unused
-       if (*client == NULL)
+       if (sd_ref == NULL) {
+               DNSSD_LOGE("DNSServiceRef is NULL");
                return FALSE;
+       }
 
        switch (condition) {
        case G_IO_IN:
-               err = DNSServiceProcessResult(*client);
+               err = DNSServiceProcessResult(sd_ref);
                if (err) {
                        DNSSD_LOGE("DNSServiceProcessResult returned %d", err);
                        return FALSE;
@@ -217,26 +257,81 @@ static gboolean __dnssd_process_result(GIOChannel *source,
        }
        return FALSE;
 }
+
+static gboolean __dnssd_handle_io_events(GIOChannel *source,
+               GIOCondition condition, gpointer data)
+{
+       dnssd_handle_s *handle = NULL;
+
+       if (data == NULL) {
+               DNSSD_LOGE("data is NULL");
+               return FALSE;
+       }
+
+       handle = (dnssd_handle_s*)data;
+       if (__dnssd_check_handle_validity(handle->service_handler) == NULL) {
+               DNSSD_LOGE("handle not found %p %u", handle, handle->service_handler);
+               return FALSE;
+       }
+
+       return __dnssd_process_result(condition, handle->sd_ref);
+}
+
+static gboolean __dnssd_resolve_data_io_events(GIOChannel *source,
+               GIOCondition condition, gpointer data)
+{
+       resolve_reply_data *reply = NULL;
+
+       if (data == NULL) {
+               DNSSD_LOGE("data is NULL");
+               return FALSE;
+       }
+
+       reply = (resolve_reply_data*)data;
+       if (__dnssd_check_resolve_reply_data_validity(reply) == NULL) {
+               DNSSD_LOGE("resolve reply data not found");
+               return FALSE;
+       }
+
+       return __dnssd_process_result(condition, reply->sd_ref);
+}
 //LCOV_EXCL_STOP
 
-void __dnssd_handle_events(int *watch_id, DNSServiceRef *sdRef)
+static guint __dnssd_io_add_watch(int fd, GIOFunc func, gpointer data)
 {
+       guint watch_id;
        GIOChannel *sock_io = NULL;
-       int dns_sd_fd = DNSServiceRefSockFD(*sdRef);
+       sock_io = g_io_channel_unix_new(fd);
+       g_io_channel_set_flags(sock_io, G_IO_FLAG_NONBLOCK, NULL);
+       g_io_channel_set_close_on_unref(sock_io, FALSE);
+       watch_id = g_io_add_watch(sock_io, (G_IO_IN | G_IO_HUP |
+                               G_IO_ERR | G_IO_NVAL), func, data);
+       DNSSD_LOGD("watch_id %u", watch_id);
+       g_io_channel_unref(sock_io);
+       return watch_id;
+}
+
+static void __dnssd_handle_add_event_handler(guint *watch_id, dnssd_handle_s *handle)
+{
+       int dns_sd_fd = DNSServiceRefSockFD(handle->sd_ref);
 
        if (dns_sd_fd < 0) {
                DNSSD_LOGE("Invalid socket fd");
                return;
        }
 
-       sock_io = g_io_channel_unix_new(dns_sd_fd);
-       g_io_channel_set_flags(sock_io, G_IO_FLAG_NONBLOCK, NULL);
-       g_io_channel_set_close_on_unref(sock_io, FALSE);
-       *watch_id = g_io_add_watch(sock_io, (G_IO_IN | G_IO_HUP |
-                               G_IO_ERR | G_IO_NVAL), __dnssd_process_result,
-                       sdRef);
-       DNSSD_LOGD("watch_id %d", *watch_id);
-       g_io_channel_unref(sock_io);
+       *watch_id = __dnssd_io_add_watch(dns_sd_fd, __dnssd_handle_io_events, handle);
+}
+
+static void __dnssd_resolve_data_add_event_handler(guint *watch_id, resolve_reply_data *data)
+{
+       int dns_sd_fd = DNSServiceRefSockFD(data->sd_ref);
+       if (dns_sd_fd < 0) {
+               DNSSD_LOGE("Invalid socket fd");
+               return;
+       }
+
+       *watch_id = __dnssd_io_add_watch(dns_sd_fd, __dnssd_resolve_data_io_events, data);
 }
 
 int dnssd_initialize(void)
@@ -287,28 +382,6 @@ int dnssd_deinitialize(void)
        return DNSSD_ERROR_NONE;
 }
 
-static dnssd_handle_s *__dnssd_check_handle_validity(
-               dnssd_service_h dnssd_service)
-{
-       __DNSSD_LOG_FUNC_ENTER__;
-       dnssd_handle_s *local_handle = NULL;
-       GSList *list;
-
-       for (list = dnssd_handle_list; list; list = list->next) {
-               local_handle = (dnssd_handle_s *)list->data;
-               if (local_handle && local_handle->service_handler ==
-                               dnssd_service) {
-                       DNSSD_LOGD("Service found with handler %u",
-                                       dnssd_service);
-                       __DNSSD_LOG_FUNC_EXIT__;
-                       return local_handle;
-               }
-       }
-
-       __DNSSD_LOG_FUNC_EXIT__;
-       return NULL;
-}
-
 int dnssd_create_local_service(const char *service_type,
                dnssd_service_h *dnssd_service)
 {
@@ -903,7 +976,7 @@ int dnssd_register_local_service(dnssd_service_h local_service,
 
        reg->callback = register_cb;
        reg->user_data = user_data;
-       __dnssd_handle_events(&(local_handle->watch_id), sd_ref);
+       __dnssd_handle_add_event_handler(&(local_handle->watch_id), local_handle);
 
        DNSSD_LOGD("Succeeded to register for dns service");
        __DNSSD_LOG_FUNC_EXIT__;
@@ -1145,7 +1218,7 @@ static int __dnssd_getaddrinfo(dnssd_handle_s *dnssd_handle, unsigned int flags,
                return ret;
        }
 
-       __dnssd_handle_events(&(local_handle->watch_id), sd_ref);
+       __dnssd_handle_add_event_handler(&(local_handle->watch_id), local_handle);
 
        DNSSD_LOGD("Succeeded to GetAddrInfo");
 
@@ -1208,7 +1281,7 @@ static int __dnssd_resolve_dns_service(dnssd_handle_s *dnssd_handle,
                return DNSSD_ERROR_OUT_OF_MEMORY;
        }
 
-       data->dnssd_handle =  dnssd_handle;
+       data->dnssd_handle = dnssd_handle;
        data->watch_id = 0;
        data->service_name = g_strdup(service_name);
 
@@ -1225,7 +1298,7 @@ static int __dnssd_resolve_dns_service(dnssd_handle_s *dnssd_handle,
                return ret;
        }
 
-       __dnssd_handle_events(&(data->watch_id), sd_ref);
+       __dnssd_resolve_data_add_event_handler(&(data->watch_id), data);
 
        DNSSD_LOGD("Succeeded to Resolve DNS Service");
 
@@ -1411,7 +1484,7 @@ int dnssd_start_browsing_service(const char *service_type,
        browse->callback = found_cb;
        browse->user_data = user_data;
        dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
-       __dnssd_handle_events(&(local_handle->watch_id), sd_ref);
+       __dnssd_handle_add_event_handler(&(local_handle->watch_id), local_handle);
 
        DNSSD_LOGD("Succeeded to browse for dns service");
        __DNSSD_LOG_FUNC_EXIT__;
@@ -1497,7 +1570,7 @@ int dnssd_start_browsing_service_on_interface(const char *service_type, const ch
        browse->callback = found_cb;
        browse->user_data = user_data;
        dnssd_handle_list = g_slist_prepend(dnssd_handle_list, local_handle);
-       __dnssd_handle_events(&(local_handle->watch_id), sd_ref);
+       __dnssd_handle_add_event_handler(&(local_handle->watch_id), local_handle);
 
        DNSSD_LOGD("Succeeded to browse for dns service");
        __DNSSD_LOG_FUNC_EXIT__;