conscache.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  1. /* Copyright (c) 2017-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. #include "core/or/or.h"
  4. #include "app/config/config.h"
  5. #include "feature/dircache/conscache.h"
  6. #include "lib/crypt_ops/crypto_util.h"
  7. #include "lib/fs/storagedir.h"
  8. #include "lib/encoding/confline.h"
  9. #define CCE_MAGIC 0x17162253
  10. #ifdef _WIN32
  11. /* On Windows, unlink won't work on a file if the file is actively mmap()ed.
  12. * That forces us to be less aggressive about unlinking files, and causes other
  13. * changes throughout our logic.
  14. */
  15. #define MUST_UNMAP_TO_UNLINK
  16. #endif /* defined(_WIN32) */
  17. /**
  18. * A consensus_cache_entry_t is a reference-counted handle to an
  19. * item in a consensus_cache_t. It can be mmapped into RAM, or not,
  20. * depending whether it's currently in use.
  21. */
  22. struct consensus_cache_entry_t {
  23. uint32_t magic; /**< Must be set to CCE_MAGIC */
  24. HANDLE_ENTRY(consensus_cache_entry, consensus_cache_entry_t);
  25. int32_t refcnt; /**< Reference count. */
  26. unsigned can_remove : 1; /**< If true, we want to delete this file. */
  27. /** If true, we intend to unmap this file as soon as we're done with it. */
  28. unsigned release_aggressively : 1;
  29. /** Filename for this object within the storage_dir_t */
  30. char *fname;
  31. /** Labels associated with this object. Immutable once the object
  32. * is created. */
  33. config_line_t *labels;
  34. /** Pointer to the cache that includes this entry (if any). */
  35. consensus_cache_t *in_cache;
  36. /** Since what time has this object been mapped into RAM, but with the cache
  37. * being the only having a reference to it? */
  38. time_t unused_since;
  39. /** mmaped contents of the underlying file. May be NULL */
  40. tor_mmap_t *map;
  41. /** Length of the body within <b>map</b>. */
  42. size_t bodylen;
  43. /** Pointer to the body within <b>map</b>. */
  44. const uint8_t *body;
  45. };
  46. /**
  47. * A consensus_cache_t holds a directory full of labeled items.
  48. */
  49. struct consensus_cache_t {
  50. /** Underling storage_dir_t to handle persistence */
  51. storage_dir_t *dir;
  52. /** List of all the entries in the directory. */
  53. smartlist_t *entries;
  54. /** The maximum number of entries that we'd like to allow in this cache.
  55. * This is the same as the storagedir limit when MUST_UNMAP_TO_UNLINK is
  56. * not defined. */
  57. unsigned max_entries;
  58. };
  59. static void consensus_cache_clear(consensus_cache_t *cache);
  60. static void consensus_cache_rescan(consensus_cache_t *);
  61. static void consensus_cache_entry_map(consensus_cache_t *,
  62. consensus_cache_entry_t *);
  63. static void consensus_cache_entry_unmap(consensus_cache_entry_t *ent);
  64. /**
  65. * Helper: Open a consensus cache in subdirectory <b>subdir</b> of the
  66. * data directory, to hold up to <b>max_entries</b> of data.
  67. */
  68. consensus_cache_t *
  69. consensus_cache_open(const char *subdir, int max_entries)
  70. {
  71. int storagedir_max_entries;
  72. consensus_cache_t *cache = tor_malloc_zero(sizeof(consensus_cache_t));
  73. char *directory = get_cachedir_fname(subdir);
  74. cache->max_entries = max_entries;
  75. #ifdef MUST_UNMAP_TO_UNLINK
  76. /* If we can't unlink the files that we're still using, then we need to
  77. * tell the storagedir backend to allow far more files than this consensus
  78. * cache actually wants, so that it can hold files which, from this cache's
  79. * perspective, have become useless.
  80. */
  81. #define VERY_LARGE_STORAGEDIR_LIMIT (1000*1000)
  82. storagedir_max_entries = VERY_LARGE_STORAGEDIR_LIMIT;
  83. #else /* !(defined(MUST_UNMAP_TO_UNLINK)) */
  84. /* Otherwise, we can just tell the storagedir to use the same limits
  85. * as this cache. */
  86. storagedir_max_entries = max_entries;
  87. #endif /* defined(MUST_UNMAP_TO_UNLINK) */
  88. cache->dir = storage_dir_new(directory, storagedir_max_entries);
  89. tor_free(directory);
  90. if (!cache->dir) {
  91. tor_free(cache);
  92. return NULL;
  93. }
  94. consensus_cache_rescan(cache);
  95. return cache;
  96. }
  97. /** Return true if it's okay to put more entries in this cache than
  98. * its official file limit.
  99. *
  100. * (We need this method on Windows, where we can't unlink files that are still
  101. * in use, and therefore might need to temporarily exceed the file limit until
  102. * the no-longer-wanted files are deletable.)
  103. */
  104. int
  105. consensus_cache_may_overallocate(consensus_cache_t *cache)
  106. {
  107. (void) cache;
  108. #ifdef MUST_UNMAP_TO_UNLINK
  109. return 1;
  110. #else
  111. return 0;
  112. #endif
  113. }
  114. /**
  115. * Tell the sandbox (if any) configured by <b>cfg</b> to allow the
  116. * operations that <b>cache</b> will need.
  117. */
  118. int
  119. consensus_cache_register_with_sandbox(consensus_cache_t *cache,
  120. struct sandbox_cfg_elem **cfg)
  121. {
  122. #ifdef MUST_UNMAP_TO_UNLINK
  123. /* Our Linux sandbox doesn't support huge file lists like the one that would
  124. * be generated by using VERY_LARGE_STORAGEDIR_LIMIT above in
  125. * consensus_cache_open(). Since the Linux sandbox is the only one we have
  126. * right now, we just assert that we never reach this point when we've had
  127. * to use VERY_LARGE_STORAGEDIR_LIMIT.
  128. *
  129. * If at some point in the future we have a different sandbox mechanism that
  130. * can handle huge file lists, we can remove this assertion or make it
  131. * conditional.
  132. */
  133. tor_assert_nonfatal_unreached();
  134. #endif /* defined(MUST_UNMAP_TO_UNLINK) */
  135. return storage_dir_register_with_sandbox(cache->dir, cfg);
  136. }
  137. /**
  138. * Helper: clear all entries from <b>cache</b> (but do not delete
  139. * any that aren't marked for removal
  140. */
  141. static void
  142. consensus_cache_clear(consensus_cache_t *cache)
  143. {
  144. consensus_cache_delete_pending(cache, 0);
  145. SMARTLIST_FOREACH_BEGIN(cache->entries, consensus_cache_entry_t *, ent) {
  146. ent->in_cache = NULL;
  147. consensus_cache_entry_decref(ent);
  148. } SMARTLIST_FOREACH_END(ent);
  149. smartlist_free(cache->entries);
  150. cache->entries = NULL;
  151. }
  152. /**
  153. * Drop all storage held by <b>cache</b>.
  154. */
  155. void
  156. consensus_cache_free_(consensus_cache_t *cache)
  157. {
  158. if (! cache)
  159. return;
  160. if (cache->entries) {
  161. consensus_cache_clear(cache);
  162. }
  163. storage_dir_free(cache->dir);
  164. tor_free(cache);
  165. }
  166. /**
  167. * Write <b>datalen</b> bytes of data at <b>data</b> into the <b>cache</b>,
  168. * labeling that data with <b>labels</b>. On failure, return NULL. On
  169. * success, return a newly created consensus_cache_entry_t.
  170. *
  171. * The returned value will be owned by the cache, and you will have a
  172. * reference to it. Call consensus_cache_entry_decref() when you are
  173. * done with it.
  174. *
  175. * The provided <b>labels</b> MUST have distinct keys: if they don't,
  176. * this API does not specify which values (if any) for the duplicate keys
  177. * will be considered.
  178. */
  179. consensus_cache_entry_t *
  180. consensus_cache_add(consensus_cache_t *cache,
  181. const config_line_t *labels,
  182. const uint8_t *data,
  183. size_t datalen)
  184. {
  185. char *fname = NULL;
  186. int r = storage_dir_save_labeled_to_file(cache->dir,
  187. labels, data, datalen, &fname);
  188. if (r < 0 || fname == NULL) {
  189. return NULL;
  190. }
  191. consensus_cache_entry_t *ent =
  192. tor_malloc_zero(sizeof(consensus_cache_entry_t));
  193. ent->magic = CCE_MAGIC;
  194. ent->fname = fname;
  195. ent->labels = config_lines_dup(labels);
  196. ent->in_cache = cache;
  197. ent->unused_since = TIME_MAX;
  198. smartlist_add(cache->entries, ent);
  199. /* Start the reference count at 2: the caller owns one copy, and the
  200. * cache owns another.
  201. */
  202. ent->refcnt = 2;
  203. return ent;
  204. }
  205. /**
  206. * Given a <b>cache</b>, return some entry for which <b>key</b>=<b>value</b>.
  207. * Return NULL if no such entry exists.
  208. *
  209. * Does not adjust reference counts.
  210. */
  211. consensus_cache_entry_t *
  212. consensus_cache_find_first(consensus_cache_t *cache,
  213. const char *key,
  214. const char *value)
  215. {
  216. smartlist_t *tmp = smartlist_new();
  217. consensus_cache_find_all(tmp, cache, key, value);
  218. consensus_cache_entry_t *ent = NULL;
  219. if (smartlist_len(tmp))
  220. ent = smartlist_get(tmp, 0);
  221. smartlist_free(tmp);
  222. return ent;
  223. }
  224. /**
  225. * Given a <b>cache</b>, add every entry to <b>out<b> for which
  226. * <b>key</b>=<b>value</b>. If <b>key</b> is NULL, add every entry.
  227. *
  228. * Do not add any entry that has been marked for removal.
  229. *
  230. * Does not adjust reference counts.
  231. */
  232. void
  233. consensus_cache_find_all(smartlist_t *out,
  234. consensus_cache_t *cache,
  235. const char *key,
  236. const char *value)
  237. {
  238. SMARTLIST_FOREACH_BEGIN(cache->entries, consensus_cache_entry_t *, ent) {
  239. if (ent->can_remove == 1) {
  240. /* We want to delete this; pretend it isn't there. */
  241. continue;
  242. }
  243. if (! key) {
  244. smartlist_add(out, ent);
  245. continue;
  246. }
  247. const char *found_val = consensus_cache_entry_get_value(ent, key);
  248. if (found_val && !strcmp(value, found_val)) {
  249. smartlist_add(out, ent);
  250. }
  251. } SMARTLIST_FOREACH_END(ent);
  252. }
  253. /**
  254. * Given a list of consensus_cache_entry_t, remove all those entries
  255. * that do not have <b>key</b>=<b>value</b> in their labels.
  256. *
  257. * Does not adjust reference counts.
  258. */
  259. void
  260. consensus_cache_filter_list(smartlist_t *lst,
  261. const char *key,
  262. const char *value)
  263. {
  264. if (BUG(lst == NULL))
  265. return; // LCOV_EXCL_LINE
  266. if (key == NULL)
  267. return;
  268. SMARTLIST_FOREACH_BEGIN(lst, consensus_cache_entry_t *, ent) {
  269. const char *found_val = consensus_cache_entry_get_value(ent, key);
  270. if (! found_val || strcmp(value, found_val)) {
  271. SMARTLIST_DEL_CURRENT(lst, ent);
  272. }
  273. } SMARTLIST_FOREACH_END(ent);
  274. }
  275. /**
  276. * If <b>ent</b> has a label with the given <b>key</b>, return its
  277. * value. Otherwise return NULL.
  278. *
  279. * The return value is only guaranteed to be valid for as long as you
  280. * hold a reference to <b>ent</b>.
  281. */
  282. const char *
  283. consensus_cache_entry_get_value(const consensus_cache_entry_t *ent,
  284. const char *key)
  285. {
  286. const config_line_t *match = config_line_find(ent->labels, key);
  287. if (match)
  288. return match->value;
  289. else
  290. return NULL;
  291. }
  292. /**
  293. * Return a pointer to the labels in <b>ent</b>.
  294. *
  295. * This pointer is only guaranteed to be valid for as long as you
  296. * hold a reference to <b>ent</b>.
  297. */
  298. const config_line_t *
  299. consensus_cache_entry_get_labels(const consensus_cache_entry_t *ent)
  300. {
  301. return ent->labels;
  302. }
  303. /**
  304. * Increase the reference count of <b>ent</b>.
  305. */
  306. void
  307. consensus_cache_entry_incref(consensus_cache_entry_t *ent)
  308. {
  309. if (BUG(ent->magic != CCE_MAGIC))
  310. return; // LCOV_EXCL_LINE
  311. ++ent->refcnt;
  312. ent->unused_since = TIME_MAX;
  313. }
  314. /**
  315. * Release a reference held to <b>ent</b>.
  316. *
  317. * If it was the last reference, ent will be freed. Therefore, you must not
  318. * use <b>ent</b> after calling this function.
  319. */
  320. void
  321. consensus_cache_entry_decref(consensus_cache_entry_t *ent)
  322. {
  323. if (! ent)
  324. return;
  325. if (BUG(ent->refcnt <= 0))
  326. return; // LCOV_EXCL_LINE
  327. if (BUG(ent->magic != CCE_MAGIC))
  328. return; // LCOV_EXCL_LINE
  329. --ent->refcnt;
  330. if (ent->refcnt == 1 && ent->in_cache) {
  331. /* Only the cache has a reference: we don't need to keep the file
  332. * mapped */
  333. if (ent->map) {
  334. if (ent->release_aggressively) {
  335. consensus_cache_entry_unmap(ent);
  336. } else {
  337. ent->unused_since = approx_time();
  338. }
  339. }
  340. return;
  341. }
  342. if (ent->refcnt > 0)
  343. return;
  344. /* Refcount is zero; we can free it. */
  345. if (ent->map) {
  346. consensus_cache_entry_unmap(ent);
  347. }
  348. tor_free(ent->fname);
  349. config_free_lines(ent->labels);
  350. consensus_cache_entry_handles_clear(ent);
  351. memwipe(ent, 0, sizeof(consensus_cache_entry_t));
  352. tor_free(ent);
  353. }
  354. /**
  355. * Mark <b>ent</b> for deletion from the cache. Deletion will not occur
  356. * until the cache is the only place that holds a reference to <b>ent</b>.
  357. */
  358. void
  359. consensus_cache_entry_mark_for_removal(consensus_cache_entry_t *ent)
  360. {
  361. ent->can_remove = 1;
  362. }
  363. /**
  364. * Mark <b>ent</b> as the kind of entry that we don't need to keep mmap'd for
  365. * any longer than we're actually using it.
  366. */
  367. void
  368. consensus_cache_entry_mark_for_aggressive_release(consensus_cache_entry_t *ent)
  369. {
  370. ent->release_aggressively = 1;
  371. }
  372. /**
  373. * Try to read the body of <b>ent</b> into memory if it isn't already
  374. * loaded. On success, set *<b>body_out</b> to the body, *<b>sz_out</b>
  375. * to its size, and return 0. On failure return -1.
  376. *
  377. * The resulting body pointer will only be valid for as long as you
  378. * hold a reference to <b>ent</b>.
  379. */
  380. int
  381. consensus_cache_entry_get_body(const consensus_cache_entry_t *ent,
  382. const uint8_t **body_out,
  383. size_t *sz_out)
  384. {
  385. if (BUG(ent->magic != CCE_MAGIC))
  386. return -1; // LCOV_EXCL_LINE
  387. if (! ent->map) {
  388. if (! ent->in_cache)
  389. return -1;
  390. consensus_cache_entry_map((consensus_cache_t *)ent->in_cache,
  391. (consensus_cache_entry_t *)ent);
  392. if (! ent->map) {
  393. return -1;
  394. }
  395. }
  396. *body_out = ent->body;
  397. *sz_out = ent->bodylen;
  398. return 0;
  399. }
  400. /**
  401. * Unmap every mmap'd element of <b>cache</b> that has been unused
  402. * since <b>cutoff</b>.
  403. */
  404. void
  405. consensus_cache_unmap_lazy(consensus_cache_t *cache, time_t cutoff)
  406. {
  407. SMARTLIST_FOREACH_BEGIN(cache->entries, consensus_cache_entry_t *, ent) {
  408. tor_assert_nonfatal(ent->in_cache == cache);
  409. if (ent->refcnt > 1 || BUG(ent->in_cache == NULL)) {
  410. /* Somebody is using this entry right now */
  411. continue;
  412. }
  413. if (ent->unused_since > cutoff) {
  414. /* Has been unused only for a little while */
  415. continue;
  416. }
  417. if (ent->map == NULL) {
  418. /* Not actually mapped. */
  419. continue;
  420. }
  421. consensus_cache_entry_unmap(ent);
  422. } SMARTLIST_FOREACH_END(ent);
  423. }
  424. /**
  425. * Return the number of currently unused filenames available in this cache.
  426. */
  427. int
  428. consensus_cache_get_n_filenames_available(consensus_cache_t *cache)
  429. {
  430. tor_assert(cache);
  431. int max = cache->max_entries;
  432. int used = smartlist_len(storage_dir_list(cache->dir));
  433. #ifdef MUST_UNMAP_TO_UNLINK
  434. if (used > max)
  435. return 0;
  436. #else
  437. tor_assert_nonfatal(max >= used);
  438. #endif /* defined(MUST_UNMAP_TO_UNLINK) */
  439. return max - used;
  440. }
  441. /**
  442. * Delete every element of <b>cache</b> has been marked with
  443. * consensus_cache_entry_mark_for_removal. If <b>force</b> is false,
  444. * retain those entries which are in use by something other than the cache.
  445. */
  446. void
  447. consensus_cache_delete_pending(consensus_cache_t *cache, int force)
  448. {
  449. SMARTLIST_FOREACH_BEGIN(cache->entries, consensus_cache_entry_t *, ent) {
  450. tor_assert_nonfatal(ent->in_cache == cache);
  451. int force_ent = force;
  452. #ifdef MUST_UNMAP_TO_UNLINK
  453. /* We cannot delete anything with an active mmap on win32, so no
  454. * force-deletion. */
  455. if (ent->map) {
  456. force_ent = 0;
  457. }
  458. #endif /* defined(MUST_UNMAP_TO_UNLINK) */
  459. if (! force_ent) {
  460. if (ent->refcnt > 1 || BUG(ent->in_cache == NULL)) {
  461. /* Somebody is using this entry right now */
  462. continue;
  463. }
  464. }
  465. if (ent->can_remove == 0) {
  466. /* Don't want to delete this. */
  467. continue;
  468. }
  469. if (BUG(ent->refcnt <= 0)) {
  470. continue; // LCOV_EXCL_LINE
  471. }
  472. SMARTLIST_DEL_CURRENT(cache->entries, ent);
  473. ent->in_cache = NULL;
  474. char *fname = tor_strdup(ent->fname); /* save a copy */
  475. consensus_cache_entry_decref(ent);
  476. storage_dir_remove_file(cache->dir, fname);
  477. tor_free(fname);
  478. } SMARTLIST_FOREACH_END(ent);
  479. }
  480. /**
  481. * Internal helper: rescan <b>cache</b> and rebuild its list of entries.
  482. */
  483. static void
  484. consensus_cache_rescan(consensus_cache_t *cache)
  485. {
  486. if (cache->entries) {
  487. consensus_cache_clear(cache);
  488. }
  489. cache->entries = smartlist_new();
  490. const smartlist_t *fnames = storage_dir_list(cache->dir);
  491. SMARTLIST_FOREACH_BEGIN(fnames, const char *, fname) {
  492. tor_mmap_t *map = NULL;
  493. config_line_t *labels = NULL;
  494. const uint8_t *body;
  495. size_t bodylen;
  496. map = storage_dir_map_labeled(cache->dir, fname,
  497. &labels, &body, &bodylen);
  498. if (! map) {
  499. /* The ERANGE error might come from tor_mmap_file() -- it means the file
  500. * was empty. EINVAL might come from ..map_labeled() -- it means the
  501. * file was misformatted. In both cases, we should just delete it.
  502. */
  503. if (errno == ERANGE || errno == EINVAL) {
  504. log_warn(LD_FS, "Found %s file %s in consensus cache; removing it.",
  505. errno == ERANGE ? "empty" : "misformatted",
  506. escaped(fname));
  507. storage_dir_remove_file(cache->dir, fname);
  508. } else {
  509. /* Can't load this; continue */
  510. log_warn(LD_FS, "Unable to map file %s from consensus cache: %s",
  511. escaped(fname), strerror(errno));
  512. }
  513. continue;
  514. }
  515. consensus_cache_entry_t *ent =
  516. tor_malloc_zero(sizeof(consensus_cache_entry_t));
  517. ent->magic = CCE_MAGIC;
  518. ent->fname = tor_strdup(fname);
  519. ent->labels = labels;
  520. ent->refcnt = 1;
  521. ent->in_cache = cache;
  522. ent->unused_since = TIME_MAX;
  523. smartlist_add(cache->entries, ent);
  524. tor_munmap_file(map); /* don't actually need to keep this around */
  525. } SMARTLIST_FOREACH_END(fname);
  526. }
  527. /**
  528. * Make sure that <b>ent</b> is mapped into RAM.
  529. */
  530. static void
  531. consensus_cache_entry_map(consensus_cache_t *cache,
  532. consensus_cache_entry_t *ent)
  533. {
  534. if (ent->map)
  535. return;
  536. ent->map = storage_dir_map_labeled(cache->dir, ent->fname,
  537. NULL, &ent->body, &ent->bodylen);
  538. ent->unused_since = TIME_MAX;
  539. }
  540. /**
  541. * Unmap <b>ent</b> from RAM.
  542. *
  543. * Do not call this if something other than the cache is holding a reference
  544. * to <b>ent</b>
  545. */
  546. static void
  547. consensus_cache_entry_unmap(consensus_cache_entry_t *ent)
  548. {
  549. ent->unused_since = TIME_MAX;
  550. if (!ent->map)
  551. return;
  552. tor_munmap_file(ent->map);
  553. ent->map = NULL;
  554. ent->body = NULL;
  555. ent->bodylen = 0;
  556. ent->unused_since = TIME_MAX;
  557. }
  558. HANDLE_IMPL(consensus_cache_entry, consensus_cache_entry_t, )
  559. #ifdef TOR_UNIT_TESTS
  560. /**
  561. * Testing only: Return true iff <b>ent</b> is mapped into memory.
  562. *
  563. * (In normal operation, this information is not exposed.)
  564. */
  565. int
  566. consensus_cache_entry_is_mapped(consensus_cache_entry_t *ent)
  567. {
  568. if (ent->map) {
  569. tor_assert(ent->body);
  570. return 1;
  571. } else {
  572. tor_assert(!ent->body);
  573. return 0;
  574. }
  575. }
  576. #endif /* defined(TOR_UNIT_TESTS) */