Fix UAF(Use After Free) issue 74/316974/8
authorinkyun.kil <inkyun.kil@samsung.com>
Mon, 2 Sep 2024 05:54:48 +0000 (14:54 +0900)
committerinkyun.kil <inkyun.kil@samsung.com>
Tue, 10 Sep 2024 04:17:12 +0000 (13:17 +0900)
- Calling the "data_control_provider_remove_data_change_consumer_filter_cb" API
  within "filter_info->callback" causes a UAF issue.

Change-Id: I908c6d5daa5c6c4a460e53f8acc52f279925d2c6
Signed-off-by: inkyun.kil <inkyun.kil@samsung.com>
src/data_control_provider.c

index b58c7faa7310fe86facca77090e2c5ff1be4a122..b684ce2215c1d95fb17b47d1ee6163eb6ed1e432 100644 (file)
@@ -168,16 +168,6 @@ static int __provider_new_request_id(void)
        return id;
 }
 
-static int __data_changed_filter_cb_info_compare_cb(gconstpointer a, gconstpointer b)
-{
-       changed_noti_consumer_filter_info_s *key1 =
-               (changed_noti_consumer_filter_info_s *)a;
-       changed_noti_consumer_filter_info_s *key2 =
-               (changed_noti_consumer_filter_info_s *)b;
-
-       return !(key1->callback_id == key2->callback_id);
-}
-
 static int __noti_consumer_app_list_compare_cb(gconstpointer a, gconstpointer b)
 {
        datacontrol_consumer_info *info_a = (datacontrol_consumer_info *)a;
@@ -1427,6 +1417,7 @@ static int __provider_noti_process(bundle *b, datacontrol_request_type type)
        char *callback_id_str = NULL;
        int callback_id = -1;
        GList *filter_iter;
+       GList *removed_iter;
        changed_noti_consumer_filter_info_s *filter_info;
        char caller_app_id[255];
        const char *pid_str;
@@ -1502,13 +1493,23 @@ static int __provider_noti_process(bundle *b, datacontrol_request_type type)
                _LOGI("DATACONTROL_TYPE_ADD_DATA_CHANGED_CB called");
                result_type = DATACONTROL_DATA_CHANGE_CALLBACK_ADD_RESULT;
                filter_iter = g_list_first(__noti_consumer_filter_info_list);
-               for (; filter_iter != NULL; filter_iter = filter_iter->next) {
-                       filter_info =
-                               (changed_noti_consumer_filter_info_s *)filter_iter->data;
-                       noti_allow = filter_info->callback(
-                                       (data_control_h)provider,
-                                       caller_app_id,
-                                       filter_info->user_data);
+               while(filter_iter) {
+                       if (filter_iter->data != NULL) {
+                               filter_info =
+                                       (changed_noti_consumer_filter_info_s *)filter_iter->data;
+                               noti_allow = filter_info->callback(
+                                               (data_control_h)provider,
+                                               caller_app_id,
+                                               filter_info->user_data);
+                               filter_iter = filter_iter->next;
+                       } else {
+                               removed_iter = filter_iter;
+                               filter_iter = filter_iter->next;
+                               __noti_consumer_filter_info_list =
+                                       g_list_remove_link(__noti_consumer_filter_info_list, removed_iter);
+                               g_list_free(removed_iter);
+                       }
+
                        if (!noti_allow)
                                break;
                }
@@ -2943,6 +2944,23 @@ out:
        return result;
 }
 
+static gboolean __remove_data_change_consumer_filter_timeout_handler(void *data)
+{
+       GList *filter_iter = g_list_first(__noti_consumer_filter_info_list);
+       while(filter_iter) {
+               GList *removed_iter = filter_iter;
+               filter_iter = filter_iter->next;
+
+               if (removed_iter->data == NULL) {
+                       __noti_consumer_filter_info_list =
+                               g_list_remove_link(__noti_consumer_filter_info_list, removed_iter);
+                       g_list_free(removed_iter);
+               }
+       }
+
+       return G_SOURCE_REMOVE;
+}
+
 EXPORT_API int data_control_provider_add_data_change_consumer_filter_cb(
                data_control_provider_data_change_consumer_filter_cb callback,
                void *user_data,
@@ -2976,26 +2994,25 @@ EXPORT_API int data_control_provider_add_data_change_consumer_filter_cb(
 EXPORT_API int data_control_provider_remove_data_change_consumer_filter_cb(int callback_id)
 {
        GList *find_list;
-       changed_noti_consumer_filter_info_s filter_info;
        changed_noti_consumer_filter_info_s *temp;
 
        if (callback_id < 1)
                return DATA_CONTROL_ERROR_INVALID_PARAMETER;
 
-       filter_info.callback_id = callback_id;
-       find_list = g_list_find_custom(__noti_consumer_filter_info_list, &filter_info,
-                       (GCompareFunc)__data_changed_filter_cb_info_compare_cb);
-       if (find_list != NULL) {
+       find_list = g_list_first(__noti_consumer_filter_info_list);
+       for (; find_list != NULL; find_list = find_list->next) {
                temp = (changed_noti_consumer_filter_info_s *)find_list->data;
-               __noti_consumer_filter_info_list =
-                       g_list_remove(__noti_consumer_filter_info_list, find_list->data);
-               free(temp);
-       } else {
-               _LOGE("invalid callback_id : %d", callback_id);
-               return DATA_CONTROL_ERROR_INVALID_PARAMETER;
+               if (temp && temp->callback_id == callback_id) {
+                       free(temp);
+                       find_list->data = NULL;
+                       g_timeout_add(10 * 1000,
+                                       __remove_data_change_consumer_filter_timeout_handler, NULL);
+                       return DATA_CONTROL_ERROR_NONE;
+               }
        }
 
-       return DATA_CONTROL_ERROR_NONE;
+       _LOGE("invalid callback_id : %d", callback_id);
+       return DATA_CONTROL_ERROR_INVALID_PARAMETER;
 }
 
 EXPORT_API int data_control_provider_send_data_change_noti(