diff options
author | Nick Mathewson <nickm@torproject.org> | 2017-12-11 16:48:44 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2017-12-11 16:48:44 -0500 |
commit | 828333e38cd45c6af4931c7158b5d007fc2876e7 (patch) | |
tree | 6472ad0af0a43b7b7d6c3ee29d823e3f7bc447a9 | |
parent | d2031f2c602c40c3cc5f96a0fba27435203e83e2 (diff) | |
parent | ea13a47791c1a6b50fed27322a073c54868ac738 (diff) | |
download | tor-828333e38cd45c6af4931c7158b5d007fc2876e7.tar.gz tor-828333e38cd45c6af4931c7158b5d007fc2876e7.zip |
Merge remote-tracking branch 'public/bug24099_031' into maint-0.3.1
-rw-r--r-- | changes/bug24099 | 4 | ||||
-rw-r--r-- | src/common/storagedir.c | 25 | ||||
-rw-r--r-- | src/or/conscache.c | 17 |
3 files changed, 39 insertions, 7 deletions
diff --git a/changes/bug24099 b/changes/bug24099 new file mode 100644 index 0000000000..dca3992664 --- /dev/null +++ b/changes/bug24099 @@ -0,0 +1,4 @@ + o Minor bugfixes (directory cache): + - Recover better from empty or corrupt files in the consensus cache + directory. Fixes bug 24099; bugfix on 0.3.1.1-alpha. + diff --git a/src/common/storagedir.c b/src/common/storagedir.c index 31933f64c2..c471ea911f 100644 --- a/src/common/storagedir.c +++ b/src/common/storagedir.c @@ -187,14 +187,19 @@ storage_dir_get_usage(storage_dir_t *d) return d->usage; } -/** Mmap a specified file within <b>d</b>. */ +/** Mmap a specified file within <b>d</b>. + * + * On failure, return NULL and set errno as for tor_mmap_file(). */ tor_mmap_t * storage_dir_map(storage_dir_t *d, const char *fname) { char *path = NULL; tor_asprintf(&path, "%s/%s", d->directory, fname); tor_mmap_t *result = tor_mmap_file(path); + int errval = errno; tor_free(path); + if (result == NULL) + errno = errval; return result; } @@ -364,6 +369,10 @@ storage_dir_save_labeled_to_file(storage_dir_t *d, * the data's size into *<b>sz_out</b>. On success, also return a tor_mmap_t * object whose contents should not be used -- it needs to be kept around, * though, for as long as <b>data_out</b> is going to be valid. + * + * On failure, set errno as for tor_mmap_file() if the file was missing or + * empty, and set errno to EINVAL if the file was not in the labeled + * format expected. */ tor_mmap_t * storage_dir_map_labeled(storage_dir_t *dir, @@ -373,13 +382,20 @@ storage_dir_map_labeled(storage_dir_t *dir, size_t *sz_out) { tor_mmap_t *m = storage_dir_map(dir, fname); - if (! m) + int errval; + if (! m) { + errval = errno; goto err; + } const char *nulp = memchr(m->data, '\0', m->size); - if (! nulp) + if (! nulp) { + errval = EINVAL; goto err; - if (labels_out && config_get_lines(m->data, labels_out, 0) < 0) + } + if (labels_out && config_get_lines(m->data, labels_out, 0) < 0) { + errval = EINVAL; goto err; + } size_t offset = nulp - m->data + 1; tor_assert(offset <= m->size); *data_out = (const uint8_t *)(m->data + offset); @@ -388,6 +404,7 @@ storage_dir_map_labeled(storage_dir_t *dir, return m; err: tor_munmap_file(m); + errno = errval; return NULL; } diff --git a/src/or/conscache.c b/src/or/conscache.c index 9e13ce8e43..33a5495974 100644 --- a/src/or/conscache.c +++ b/src/or/conscache.c @@ -539,9 +539,20 @@ consensus_cache_rescan(consensus_cache_t *cache) map = storage_dir_map_labeled(cache->dir, fname, &labels, &body, &bodylen); if (! map) { - /* Can't load this; continue */ - log_warn(LD_FS, "Unable to map file %s from consensus cache: %s", - escaped(fname), strerror(errno)); + /* The ERANGE error might come from tor_mmap_file() -- it means the file + * was empty. EINVAL might come from ..map_labeled() -- it means the + * file was misformatted. In both cases, we should just delete it. + */ + if (errno == ERANGE || errno == EINVAL) { + log_warn(LD_FS, "Found %s file %s in consensus cache; removing it.", + errno == ERANGE ? "empty" : "misformatted", + escaped(fname)); + storage_dir_remove_file(cache->dir, fname); + } else { + /* Can't load this; continue */ + log_warn(LD_FS, "Unable to map file %s from consensus cache: %s", + escaped(fname), strerror(errno)); + } continue; } consensus_cache_entry_t *ent = |