From 0e8ed1f261cf336ce1ec8b3b514e4794ac8f058c Mon Sep 17 00:00:00 2001 From: Brian Gix Date: Wed, 20 May 2020 15:14:38 -0700 Subject: [PATCH] mesh: Fix double-free 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. --- mesh/mesh-config-json.c | 5 +---- mesh/mesh-config.h | 2 +- mesh/node.c | 20 +++++++------------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/mesh/mesh-config-json.c b/mesh/mesh-config-json.c index 6567d761c..d3f423e50 100644 --- a/mesh/mesh-config-json.c +++ b/mesh/mesh-config-json.c @@ -2309,7 +2309,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]; @@ -2330,7 +2330,4 @@ void mesh_config_destroy(struct mesh_config *cfg) return; del_path(node_dir); - - /* Release node config object */ - mesh_config_release(cfg); } diff --git a/mesh/mesh-config.h b/mesh/mesh-config.h index 25002f5a7..8ff7b63c7 100644 --- a/mesh/mesh-config.h +++ b/mesh/mesh-config.h @@ -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, diff --git a/mesh/node.c b/mesh/node.c index 2b4b3a563..d5e07ce7f 100644 --- a/mesh/node.c +++ b/mesh/node.c @@ -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); } -- 2.47.3