Fix memory leaks and bad-free in cache and crypto sector log

pcache.c: cache_timer and pcache_clean called pmem_free(he->value)
directly instead of he->free(he->value), skipping the registered free
callback. This caused all cached SSL connections, TLS sessions, and
crypto decoders to leak their internal mbedtls state on eviction and
shutdown. Same bug fixed in pcache_clean_oneof.

pfscrypto.c: ptree_for_each_element_call_safe passed bare free() to
free psync_sector_inlog_t nodes, but those are allocated via pmem_malloc
which prepends a 16-byte header. Add free_sector_inlog() helper that
calls pmem_free and use it at both call sites.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-10 13:23:05 +01:00
parent 5bf15f5fdc
commit a48be6dbc3
2 changed files with 9 additions and 5 deletions

View File

@ -81,7 +81,7 @@ static void cache_timer(psync_timer_t timer, void *ptr) {
pthread_mutex_lock(&cachelocks[hash_to_lock(he->hash)]);
psync_list_del(&he->list);
pthread_mutex_unlock(&cachelocks[hash_to_lock(he->hash)]);
pmem_free(PMEM_SUBSYS_OTHER, he->value);
he->free(he->value);
pmem_free(PMEM_SUBSYS_OTHER, he);
ptimer_stop(timer);
}
@ -229,7 +229,7 @@ void pcache_clean() {
he = psync_list_element(l1, cache_entry_t, list);
if (!ptimer_stop(he->timer)) {
psync_list_del(l1);
pmem_free(PMEM_SUBSYS_OTHER, he->value);
he->free(he->value);
pmem_free(PMEM_SUBSYS_OTHER, he);
}
}
@ -256,7 +256,7 @@ void pcache_clean_oneof(const char **prefixes, size_t cnt) {
continue;
if (!ptimer_stop(he->timer)) {
psync_list_del(l1);
pmem_free(PMEM_SUBSYS_OTHER, he->value);
he->free(he->value);
pmem_free(PMEM_SUBSYS_OTHER, he);
}
}

View File

@ -531,6 +531,10 @@ int pfs_crpt_read_new(psync_openfile_t *of, char *buf,
return rd;
}
static void free_sector_inlog(psync_sector_inlog_t *e) {
pmem_free(PMEM_SUBSYS_OTHER, e);
}
static void
pfs_crypto_set_sector_log_offset(psync_openfile_t *of,
psync_crypto_sectorid_t sectorid,
@ -1093,7 +1097,7 @@ static int pfs_crypto_do_finalize_log(psync_openfile_t *of, int fullsync) {
pmem_free(PMEM_SUBSYS_OTHER, flog);
return -EIO;
}
ptree_for_each_element_call_safe(of->sectorsinlog, psync_sector_inlog_t, tree, free);
ptree_for_each_element_call_safe(of->sectorsinlog, psync_sector_inlog_t, tree, free_sector_inlog);
of->sectorsinlog = PSYNC_TREE_EMPTY;
ret = pfs_crypto_log_flush_and_process(of, flog, 0, 1);
pfile_delete(flog);
@ -1690,7 +1694,7 @@ static int pfs_crpt_truncate_to_zero(psync_openfile_t *of) {
psync_interval_tree_add(&of->writeintervals, 0,
pfs_crpt_crypto_size(of->initialsize));
}
ptree_for_each_element_call_safe(of->sectorsinlog, psync_sector_inlog_t, tree, free);
ptree_for_each_element_call_safe(of->sectorsinlog, psync_sector_inlog_t, tree, free_sector_inlog);
of->sectorsinlog = PSYNC_TREE_EMPTY;
of->currentsize = 0;
pfs_crypto_kill_extender_locked(of);