mesh: Fix double-free 31/234231/1 accepted/tizen/unified/20200529.124353 submit/tizen/20200527.022320
authorBrian Gix <brian.gix@intel.com>
Wed, 20 May 2020 22:14:38 +0000 (15:14 -0700)
committerAbhay Agarwal <ay.agarwal@samsung.com>
Fri, 22 May 2020 04:23:44 +0000 (09:53 +0530)
This fixes a double-free error when destroying the NVM storage of a mesh node.
Cleanly handle two distinct scenarios:

1. When the node is being deleted at runtime.  This causes release of
   both dynamic memory and NVM storage.

2. During shutdown, we release dynamic memory only.

Change-Id: Ib69263c627e08f396d2f5dacbc04b4cfe0aace35
Signed-off-by: Abhay Agarwal <ay.agarwal@samsung.com>
mesh/mesh-config-json.c
mesh/mesh-config.h
mesh/node.c

index a00638d..23259af 100644 (file)
@@ -2310,7 +2310,7 @@ bool mesh_config_load_nodes(const char *cfgdir_name, mesh_config_node_func_t cb,
        return true;
 }
 
-void mesh_config_destroy(struct mesh_config *cfg)
+void mesh_config_destroy_nvm(struct mesh_config *cfg)
 {
        char *node_dir, *node_name;
        char uuid[33];
@@ -2331,7 +2331,4 @@ void mesh_config_destroy(struct mesh_config *cfg)
                return;
 
        del_path(node_dir);
-
-       /* Release node config object */
-       mesh_config_release(cfg);
 }
index 25002f5..8ff7b63 100644 (file)
@@ -114,7 +114,7 @@ typedef bool (*mesh_config_node_func_t)(struct mesh_config_node *node,
 bool mesh_config_load_nodes(const char *cfgdir_name, mesh_config_node_func_t cb,
                                                        void *user_data);
 void mesh_config_release(struct mesh_config *cfg);
-void mesh_config_destroy(struct mesh_config *cfg);
+void mesh_config_destroy_nvm(struct mesh_config *cfg);
 bool mesh_config_save(struct mesh_config *cfg, bool no_wait,
                                mesh_config_status_func_t cb, void *user_data);
 struct mesh_config *mesh_config_create(const char *cfgdir_name,
index 7084871..2d9c4ee 100644 (file)
@@ -323,18 +323,16 @@ static void free_node_resources(void *data)
        struct mesh_node *node = data;
 
        /* Unregister io callbacks */
-       if (node->net)
-               mesh_net_detach(node->net);
+       mesh_net_detach(node->net);
 
-       l_queue_destroy(node->elements, element_free);
-       node->elements = NULL;
 
        /* In case of a provisioner, stop active scanning */
        if (node->provisioner)
                manager_scan_cancel(node);
 
+       /* Free dynamic resources */
        free_node_dbus_resources(node);
-
+       l_queue_destroy(node->elements, element_free);
        mesh_config_release(node->cfg);
        mesh_net_free(node->net);
        l_free(node->storage_dir);
@@ -352,8 +350,7 @@ void node_remove(struct mesh_node *node)
 
        l_queue_remove(nodes, node);
 
-       if (node->cfg)
-               mesh_config_destroy(node->cfg);
+       mesh_config_destroy_nvm(node->cfg);
 
        free_node_resources(node);
 }
@@ -576,13 +573,10 @@ fail:
 static void cleanup_node(void *data)
 {
        struct mesh_node *node = data;
-       struct mesh_net *net = node->net;
+       uint32_t seq_num = mesh_net_get_seq_num(node->net);
 
-       /* Preserve the last sequence number */
-       if (node->cfg)
-               mesh_config_write_seq_number(node->cfg,
-                                               mesh_net_get_seq_num(net),
-                                               false);
+       /* Preserve the last used sequence number */
+       mesh_config_write_seq_number(node->cfg, seq_num, false);
 
        free_node_resources(node);
 }