/** Free all storage held by the service descriptor cache. */ void rend_cache_free_all(void) { strmap_free(rend_cache, rend_cache_entry_free_); digestmap_free(rend_cache_v2_dir, rend_cache_entry_free_); strmap_free(rend_cache_failure, rend_cache_failure_entry_free_); rend_cache = NULL; rend_cache_v2_dir = NULL; rend_cache_failure = NULL; rend_cache_total_allocation = 0; }
static void test_rend_cache_failure_purge(void *data) { (void)data; // Handles a null failure cache strmap_free(rend_cache_failure, rend_cache_failure_entry_free_); rend_cache_failure = NULL; rend_cache_failure_purge(); tt_ptr_op(rend_cache_failure, OP_NE, NULL); tt_int_op(strmap_size(rend_cache_failure), OP_EQ, 0); done: rend_cache_free_all(); }
void seqenc_free(seqenc_t* E) { if (E == NULL) return; str_free(&E->tmpseq); ac_free(E->ac); cond_dist16_free(&E->cs); size_t i; for (i = 0; i < prefix_len; ++i) { cond_dist16_free(&E->cs0[i]); } free(E->d_nmask); uint32_enc_free(&E->d_contig_off); cond_dist4_free(&E->supercontig_motif); uint32_enc_free(&E->d_ext_flags); cond_dist128_free(&E->d_ext_seqname); size_t refsize = strmap_size(E->seq_index); for (i = 0; i < refsize; ++i) { cond_dist256_free(&E->d_ext_pos[i]); } free(E->d_ext_pos); cond_dist16_free(&E->d_ext_cigar_op); uint32_enc_free(&E->d_ext_cigar_n); for (i = 0; i < 9; ++i) { uint32_enc_free(&E->d_ext_cigar_len[i]); } uint32_enc_free(&E->d_ext_tlen); strmap_free(E->seq_index); free(E); }
/** * Protects all the strings in the sandbox's parameter list configuration. It * works by calculating the total amount of memory required by the parameter * list, allocating the memory using mmap, and protecting it from writes with * mprotect(). */ static int prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg) { int ret = 0; size_t pr_mem_size = 0, pr_mem_left = 0; char *pr_mem_next = NULL, *pr_mem_base; sandbox_cfg_t *el = NULL; strmap_t *locations = NULL; // get total number of bytes required to mmap. (Overestimate.) for (el = cfg; el != NULL; el = el->next) { pr_mem_size += strlen((char*) el->param->value) + 1; if (el->param->value2) pr_mem_size += strlen((char*) el->param->value2) + 1; } // allocate protected memory with MALLOC_MP_LIM canary pr_mem_base = (char*) mmap(NULL, MALLOC_MP_LIM + pr_mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); if (pr_mem_base == MAP_FAILED) { log_err(LD_BUG,"(Sandbox) failed allocate protected memory! mmap: %s", strerror(errno)); ret = -1; goto out; } pr_mem_next = pr_mem_base + MALLOC_MP_LIM; pr_mem_left = pr_mem_size; locations = strmap_new(); // change el value pointer to protected for (el = cfg; el != NULL; el = el->next) { if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left, &el->param->value) < 0) { ret = -2; goto out; } if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left, &el->param->value2) < 0) { ret = -2; goto out; } el->param->prot = 1; } // protecting from writes if (mprotect(pr_mem_base, MALLOC_MP_LIM + pr_mem_size, PROT_READ)) { log_err(LD_BUG,"(Sandbox) failed to protect memory! mprotect: %s", strerror(errno)); ret = -3; goto out; } /* * Setting sandbox restrictions so the string memory cannot be tampered with */ // no mremap of the protected base address ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(mremap), SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); if (ret) { log_err(LD_BUG,"(Sandbox) mremap protected memory filter fail!"); goto out; } // no munmap of the protected base address ret = seccomp_rule_add_1(ctx, SCMP_ACT_KILL, SCMP_SYS(munmap), SCMP_CMP(0, SCMP_CMP_EQ, (intptr_t) pr_mem_base)); if (ret) { log_err(LD_BUG,"(Sandbox) munmap protected memory filter fail!"); goto out; } /* * Allow mprotect with PROT_READ|PROT_WRITE because openssl uses it, but * never over the memory region used by the protected strings. * * PROT_READ|PROT_WRITE was originally fully allowed in sb_mprotect(), but * had to be removed due to limitation of libseccomp regarding intervals. * * There is a restriction on how much you can mprotect with R|W up to the * size of the canary. */ ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base), SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (LT)!"); goto out; } ret = seccomp_rule_add_3(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size + MALLOC_MP_LIM), SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); if (ret) { log_err(LD_BUG,"(Sandbox) mprotect protected memory filter fail (GT)!"); goto out; } out: strmap_free(locations, NULL); return ret; }
/** Run unit tests for string-to-void* map functions */ static void test_container_strmap(void) { strmap_t *map; strmap_iter_t *iter; const char *k; void *v; char *visited = NULL; smartlist_t *found_keys = NULL; map = strmap_new(); test_assert(map); test_eq(strmap_size(map), 0); test_assert(strmap_isempty(map)); v = strmap_set(map, "K1", (void*)99); test_eq_ptr(v, NULL); test_assert(!strmap_isempty(map)); v = strmap_set(map, "K2", (void*)101); test_eq_ptr(v, NULL); v = strmap_set(map, "K1", (void*)100); test_eq_ptr(v, (void*)99); test_eq_ptr(strmap_get(map,"K1"), (void*)100); test_eq_ptr(strmap_get(map,"K2"), (void*)101); test_eq_ptr(strmap_get(map,"K-not-there"), NULL); strmap_assert_ok(map); v = strmap_remove(map,"K2"); strmap_assert_ok(map); test_eq_ptr(v, (void*)101); test_eq_ptr(strmap_get(map,"K2"), NULL); test_eq_ptr(strmap_remove(map,"K2"), NULL); strmap_set(map, "K2", (void*)101); strmap_set(map, "K3", (void*)102); strmap_set(map, "K4", (void*)103); test_eq(strmap_size(map), 4); strmap_assert_ok(map); strmap_set(map, "K5", (void*)104); strmap_set(map, "K6", (void*)105); strmap_assert_ok(map); /* Test iterator. */ iter = strmap_iter_init(map); found_keys = smartlist_new(); while (!strmap_iter_done(iter)) { strmap_iter_get(iter,&k,&v); smartlist_add(found_keys, tor_strdup(k)); test_eq_ptr(v, strmap_get(map, k)); if (!strcmp(k, "K2")) { iter = strmap_iter_next_rmv(map,iter); } else { iter = strmap_iter_next(map,iter); } } /* Make sure we removed K2, but not the others. */ test_eq_ptr(strmap_get(map, "K2"), NULL); test_eq_ptr(strmap_get(map, "K5"), (void*)104); /* Make sure we visited everyone once */ smartlist_sort_strings(found_keys); visited = smartlist_join_strings(found_keys, ":", 0, NULL); test_streq(visited, "K1:K2:K3:K4:K5:K6"); strmap_assert_ok(map); /* Clean up after ourselves. */ strmap_free(map, NULL); map = NULL; /* Now try some lc functions. */ map = strmap_new(); strmap_set_lc(map,"Ab.C", (void*)1); test_eq_ptr(strmap_get(map,"ab.c"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), (void*)1); test_eq_ptr(strmap_get(map,"AB.C"), NULL); test_eq_ptr(strmap_remove_lc(map,"aB.C"), (void*)1); strmap_assert_ok(map); test_eq_ptr(strmap_get_lc(map,"AB.C"), NULL); done: if (map) strmap_free(map,NULL); if (found_keys) { SMARTLIST_FOREACH(found_keys, char *, cp, tor_free(cp)); smartlist_free(found_keys); } tor_free(visited); }
/** Run unit tests for threading logic. */ static void test_threads_basic(void *arg) { char *s1 = NULL, *s2 = NULL; int done = 0, timedout = 0; time_t started; #ifndef _WIN32 struct timeval tv; tv.tv_sec=0; tv.tv_usec=100*1000; #endif (void) arg; set_main_thread(); thread_test_mutex_ = tor_mutex_new(); thread_test_start1_ = tor_mutex_new(); thread_test_start2_ = tor_mutex_new(); thread_test_strmap_ = strmap_new(); s1 = tor_strdup("thread 1"); s2 = tor_strdup("thread 2"); tor_mutex_acquire(thread_test_start1_); tor_mutex_acquire(thread_test_start2_); spawn_func(thread_test_func_, s1); spawn_func(thread_test_func_, s2); tor_mutex_release(thread_test_start2_); tor_mutex_release(thread_test_start1_); started = time(NULL); while (!done) { tor_mutex_acquire(thread_test_mutex_); strmap_assert_ok(thread_test_strmap_); if (strmap_get(thread_test_strmap_, "thread 1") && strmap_get(thread_test_strmap_, "thread 2")) { done = 1; } else if (time(NULL) > started + 150) { timedout = done = 1; } tor_mutex_release(thread_test_mutex_); #ifndef _WIN32 /* Prevent the main thread from starving the worker threads. */ select(0, NULL, NULL, NULL, &tv); #endif } tor_mutex_acquire(thread_test_start1_); tor_mutex_release(thread_test_start1_); tor_mutex_acquire(thread_test_start2_); tor_mutex_release(thread_test_start2_); tor_mutex_free(thread_test_mutex_); if (timedout) { printf("\nTimed out: %d %d", t1_count, t2_count); tt_assert(strmap_get(thread_test_strmap_, "thread 1")); tt_assert(strmap_get(thread_test_strmap_, "thread 2")); tt_assert(!timedout); } /* different thread IDs. */ tt_assert(strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "thread 2"))); tt_assert(!strcmp(strmap_get(thread_test_strmap_, "thread 1"), strmap_get(thread_test_strmap_, "last to run")) || !strcmp(strmap_get(thread_test_strmap_, "thread 2"), strmap_get(thread_test_strmap_, "last to run"))); tt_int_op(thread_fns_failed, ==, 0); tt_int_op(thread_fn_tid1, !=, thread_fn_tid2); done: tor_free(s1); tor_free(s2); tor_free(thread1_name_); tor_free(thread2_name_); if (thread_test_strmap_) strmap_free(thread_test_strmap_, NULL); if (thread_test_start1_) tor_mutex_free(thread_test_start1_); if (thread_test_start2_) tor_mutex_free(thread_test_start2_); }