Merge remote-tracking branch 'public/bug24099_031' into maint-0.3.1

This commit is contained in:
Nick Mathewson 2017-12-11 16:48:44 -05:00
commit 828333e38c
3 changed files with 39 additions and 7 deletions

4
changes/bug24099 Normal file
View File

@ -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.

View File

@ -187,14 +187,19 @@ storage_dir_get_usage(storage_dir_t *d)
return d->usage; 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 * tor_mmap_t *
storage_dir_map(storage_dir_t *d, const char *fname) storage_dir_map(storage_dir_t *d, const char *fname)
{ {
char *path = NULL; char *path = NULL;
tor_asprintf(&path, "%s/%s", d->directory, fname); tor_asprintf(&path, "%s/%s", d->directory, fname);
tor_mmap_t *result = tor_mmap_file(path); tor_mmap_t *result = tor_mmap_file(path);
int errval = errno;
tor_free(path); tor_free(path);
if (result == NULL)
errno = errval;
return result; 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 * 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, * 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. * 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 * tor_mmap_t *
storage_dir_map_labeled(storage_dir_t *dir, storage_dir_map_labeled(storage_dir_t *dir,
@ -373,13 +382,20 @@ storage_dir_map_labeled(storage_dir_t *dir,
size_t *sz_out) size_t *sz_out)
{ {
tor_mmap_t *m = storage_dir_map(dir, fname); tor_mmap_t *m = storage_dir_map(dir, fname);
if (! m) int errval;
if (! m) {
errval = errno;
goto err; goto err;
}
const char *nulp = memchr(m->data, '\0', m->size); const char *nulp = memchr(m->data, '\0', m->size);
if (! nulp) if (! nulp) {
errval = EINVAL;
goto err; 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; goto err;
}
size_t offset = nulp - m->data + 1; size_t offset = nulp - m->data + 1;
tor_assert(offset <= m->size); tor_assert(offset <= m->size);
*data_out = (const uint8_t *)(m->data + offset); *data_out = (const uint8_t *)(m->data + offset);
@ -388,6 +404,7 @@ storage_dir_map_labeled(storage_dir_t *dir,
return m; return m;
err: err:
tor_munmap_file(m); tor_munmap_file(m);
errno = errval;
return NULL; return NULL;
} }

View File

@ -539,9 +539,20 @@ consensus_cache_rescan(consensus_cache_t *cache)
map = storage_dir_map_labeled(cache->dir, fname, map = storage_dir_map_labeled(cache->dir, fname,
&labels, &body, &bodylen); &labels, &body, &bodylen);
if (! map) { if (! map) {
/* 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 */ /* Can't load this; continue */
log_warn(LD_FS, "Unable to map file %s from consensus cache: %s", log_warn(LD_FS, "Unable to map file %s from consensus cache: %s",
escaped(fname), strerror(errno)); escaped(fname), strerror(errno));
}
continue; continue;
} }
consensus_cache_entry_t *ent = consensus_cache_entry_t *ent =