From f73f697142bd5ce32d9b7273ed73ea798594854d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Thu, 5 Sep 2019 19:56:29 +0200 Subject: [PATCH] Call fsync() on the configuration directories where appropriate. Just ensuring individual config files are written atomically is good enough to keep internal consistency, but we want to make sure directory metadata is also synced to disk when returning from functions that expect the changes to have been made permanent, such as meshlink_import() and meshlink_blacklist(). Also do this when we create the initial directory structure. We already took care of syncing directory metadata when rotating keys for encrypted storage. --- src/conf.c | 28 ++++++++++++++++++++++++++++ src/conf.h | 1 + src/meshlink.c | 17 +++++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/src/conf.c b/src/conf.c index bafa87d4..8244ba7c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -80,18 +80,21 @@ static bool sync_path(const char *pathname) { if(fd < 0) { logger(NULL, MESHLINK_ERROR, "Failed to open %s: %s\n", pathname, strerror(errno)); + meshlink_errno = MESHLINK_ESTORAGE; return false; } if(fsync(fd)) { logger(NULL, MESHLINK_ERROR, "Failed to sync %s: %s\n", pathname, strerror(errno)); close(fd); + meshlink_errno = MESHLINK_ESTORAGE; return false; } if(close(fd)) { logger(NULL, MESHLINK_ERROR, "Failed to close %s: %s\n", pathname, strerror(errno)); close(fd); + meshlink_errno = MESHLINK_ESTORAGE; return false; } @@ -343,6 +346,31 @@ bool config_rename(meshlink_handle_t *mesh, const char *old_conf_subdir, const c return rename(old_path, new_path) == 0; } +bool config_sync(meshlink_handle_t *mesh, const char *conf_subdir) { + if(!mesh->confbase) { + return true; + } + + if(!conf_subdir) { + return false; + } + + char path[PATH_MAX]; + snprintf(path, sizeof(path), "%s" SLASH "%s" SLASH "hosts", mesh->confbase, conf_subdir); + + if(!sync_path(path)) { + return false; + } + + snprintf(path, sizeof(path), "%s" SLASH "%s", mesh->confbase, conf_subdir); + + if(!sync_path(path)) { + return false; + } + + return true; +} + bool meshlink_confbase_exists(meshlink_handle_t *mesh) { if(!mesh->confbase) { return false; diff --git a/src/conf.h b/src/conf.h index 93ee5bb9..b3763ea7 100644 --- a/src/conf.h +++ b/src/conf.h @@ -39,6 +39,7 @@ extern bool config_init(struct meshlink_handle *mesh, const char *conf_subdir); extern bool config_destroy(const char *confbase, const char *conf_subdir); extern bool config_copy(struct meshlink_handle *mesh, const char *src_dir_name, const void *src_key, const char *dst_dir_name, const void *dst_key); extern bool config_rename(struct meshlink_handle *mesh, const char *old_conf_subdir, const char *new_conf_subdir); +extern bool config_sync(struct meshlink_handle *mesh, const char *conf_subdir); extern bool main_config_exists(struct meshlink_handle *mesh, const char *conf_subdir); extern bool main_config_lock(struct meshlink_handle *mesh); diff --git a/src/meshlink.c b/src/meshlink.c index ebe585d2..164c9937 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -661,6 +661,11 @@ static bool finalize_join(meshlink_handle_t *mesh, const void *buf, uint16_t len } } + /* Ensure the configuration directory metadata is on disk */ + if(!config_sync(mesh, "current")) { + return false; + } + sptps_send_record(&(mesh->sptps), 1, ecdsa_get_public_key(mesh->private_key), 32); logger(mesh, MESHLINK_DEBUG, "Configuration stored in: %s\n", mesh->confbase); @@ -890,6 +895,11 @@ static bool meshlink_setup(meshlink_handle_t *mesh) { return false; } + /* Ensure the configuration directory metadata is on disk */ + if(!config_sync(mesh, "current")) { + return false; + } + if(!main_config_lock(mesh)) { logger(NULL, MESHLINK_ERROR, "Cannot lock main config file\n"); meshlink_errno = MESHLINK_ESTORAGE; @@ -2711,6 +2721,10 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) { return false; } + if(!config_sync(mesh, "current")) { + return false; + } + return true; } @@ -2740,6 +2754,8 @@ void meshlink_blacklist(meshlink_handle_t *mesh, meshlink_node_t *node) { n->status.blacklisted = true; node_write_config(mesh, n); + config_sync(mesh, "current"); + logger(mesh, MESHLINK_DEBUG, "Blacklisted %s.\n", node->name); //Immediately terminate any connections we have with the blacklisted node @@ -2783,6 +2799,7 @@ void meshlink_whitelist(meshlink_handle_t *mesh, meshlink_node_t *node) { n->status.blacklisted = false; node_write_config(mesh, n); + config_sync(mesh, "current"); pthread_mutex_unlock(&(mesh->mesh_mutex)); return; -- 2.39.2