Add a mutex for the ap_handle_list 31/255931/1 accepted/tizen/unified/20210329.145051 submit/tizen/20210325.101906
authorSeonah Moon <seonah1.moon@samsung.com>
Thu, 25 Mar 2021 05:47:17 +0000 (14:47 +0900)
committerSeonah Moon <seonah1.moon@samsung.com>
Thu, 25 Mar 2021 05:59:44 +0000 (14:59 +0900)
In CLR environment, GC can release an ap handle in non-main thread.
The problem is that add() operation for an ap handle can arise during GC
working in main or other thread. In this case, the ap_handle_list is accessed
at the same time in main and non-main thread.
This can make a memory corruption of the ap_handle_list.

Change-Id: I7e6a37751e746153d2f6610fc340b44c1e498f25

include/wifi_internal.h
packaging/capi-network-wifi-manager.spec
src/wifi_internal.c

index 87c1ea3..1e96bdf 100755 (executable)
@@ -21,6 +21,7 @@
 #include <glib.h>
 #include <vconf/vconf.h>
 #include <system_info.h>
+#include <pthread.h>
 
 #include "wifi-manager.h"
 #include "wifi-manager-extension.h"
@@ -264,6 +265,7 @@ typedef struct {
        bool is_disconnect_wps_pbc;
        bool is_disconnect_wps_pin;
 
+       pthread_mutex_t mutex_ap_handle_list;
        GSList *ap_handle_list;
        GSList *config_handle_list;
 
index e1b76f4..1158151 100755 (executable)
@@ -1,6 +1,6 @@
 Name:          capi-network-wifi-manager
 Summary:       Network Wi-Fi library in TIZEN C API
-Version:       1.3.6
+Version:       1.3.7
 Release:       1
 Group:         System/Network
 License:       Apache-2.0
index d29a5cf..246daef 100755 (executable)
@@ -1525,6 +1525,7 @@ int _wifi_create_handle(wifi_manager_h *wifi)
                return WIFI_MANAGER_ERROR_OUT_OF_MEMORY; //LCOV_EXCL_LINE
        }
 
+       pthread_mutex_init(&(wifi_handle->mutex_ap_handle_list), NULL);
        *wifi = wifi_handle;
 
        WIFI_LOG(WIFI_INFO, "New handle create[%p]", *wifi);
@@ -1534,6 +1535,11 @@ int _wifi_create_handle(wifi_manager_h *wifi)
 
 void _wifi_destroy_handle(wifi_manager_h wifi)
 {
+       if (!wifi)
+               return;
+
+       wifi_manager_handle_s *wifi_handle = (wifi_manager_handle_s *)wifi;
+       pthread_mutex_destroy(&(wifi_handle->mutex_ap_handle_list));
        g_free(wifi);
 }
 
@@ -1620,13 +1626,36 @@ static void __free_dpp(gpointer data)
 }
 //LCOV_EXCL_STOP
 
+static void _wifi_ap_handle_list_lock(wifi_manager_handle_s *wifi)
+{
+       if (!wifi)
+               return;
+
+       int ret = pthread_mutex_lock(&(wifi->mutex_ap_handle_list));
+       if (ret < 0)
+               WIFI_LOG(WIFI_ERROR, "Failed to lock the ap_handle_list[%d]", ret);
+}
+
+static void _wifi_ap_handle_list_unlock(wifi_manager_handle_s *wifi)
+{
+       if (!wifi)
+               return;
+
+       int ret = pthread_mutex_unlock(&(wifi->mutex_ap_handle_list));
+       if (ret < 0)
+               WIFI_LOG(WIFI_ERROR, "Failed to lock the ap_handle_list[%d]", ret);
+}
+
 void _wifi_deinit(wifi_manager_h wifi)
 {
        wifi_manager_handle_s *wifi_handle = wifi;
 
        net_deregister_client_ext(wifi_handle->network_info);
 
+       _wifi_ap_handle_list_lock((wifi_manager_handle_s *)wifi);
        __clear_profile_list(&(wifi_handle->ap_handle_list));
+       _wifi_ap_handle_list_unlock((wifi_manager_handle_s *)wifi);
+
        __clear_profile_list(&(wifi_handle->profile_iterator));
        __clear_profile_list(&(wifi_handle->specific_profile_iterator));
        __clear_profile_list(&(wifi_handle->bss_profile_iterator));
@@ -1766,8 +1795,12 @@ bool _wifi_check_ap_validity(net_profile_info_s *ap_info)
        if (_wifi_find_from_handle_list(wifi_handle) == false)
                return false;
 
-       if (g_slist_find(wifi_handle->ap_handle_list, ap_info) != NULL)
+       _wifi_ap_handle_list_lock(wifi_handle);
+       if (g_slist_find(wifi_handle->ap_handle_list, ap_info) != NULL) {
+               _wifi_ap_handle_list_unlock(wifi_handle);
                return true;
+       }
+       _wifi_ap_handle_list_unlock(wifi_handle);
 
        if (g_slist_find(wifi_handle->profile_iterator, ap_info) != NULL)
                return true;
@@ -1792,8 +1825,10 @@ void _wifi_add_to_ap_list(net_profile_info_s *ap_info)
 
        wifi_handle = network_info->wifi_handle;
        if (wifi_handle) {
+               _wifi_ap_handle_list_lock(wifi_handle);
                wifi_handle->ap_handle_list =
-                       g_slist_append(wifi_handle->ap_handle_list, ap_info);
+                       g_slist_prepend(wifi_handle->ap_handle_list, ap_info);
+               _wifi_ap_handle_list_unlock(wifi_handle);
        }
 }
 
@@ -1808,8 +1843,10 @@ void _wifi_remove_from_ap_list(net_profile_info_s *ap_info)
 
        wifi_handle = network_info->wifi_handle;
        if (wifi_handle) {
+               _wifi_ap_handle_list_lock(wifi_handle);
                wifi_handle->ap_handle_list =
                        g_slist_remove(wifi_handle->ap_handle_list, ap_info);
+               _wifi_ap_handle_list_unlock(wifi_handle);
        }
 }