Fix bad-free in pfs.c and ppagecache.c (pcl-26j)

Two more call sites passed bare free() as a callback to tree/list
traversal macros, but the nodes were allocated via pmem_malloc which
prepends a pmem_header_t. Freeing the data pointer directly skips the
header and corrupts the heap.

- pfs.c: ptree_for_each_element_call_safe on sectorsinlog used free()
  on psync_sector_inlog_t; replaced with free_sector_inlog_node() that
  calls pmem_free(PMEM_SUBSYS_OTHER, e).
- ppagecache.c: psync_list_for_each_element_call on request->ranges
  used free() on psync_request_range_t; replaced with
  free_request_range() that calls pmem_free(PMEM_SUBSYS_CACHE, range).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-22 15:32:50 +01:00
parent 69fb9accf9
commit a94cf561fb
2 changed files with 14 additions and 2 deletions

View File

@ -1745,6 +1745,12 @@ static void close_if_valid(int fd) {
pfile_close(fd);
}
/* Free a psync_sector_inlog_t node allocated via pmem_malloc. Used as the
* callback for ptree_for_each_element_call_safe when bulk-freeing the tree. */
static void free_sector_inlog_node(psync_sector_inlog_t *e) {
pmem_free(PMEM_SUBSYS_OTHER, e);
}
static void pfs_free_openfile(psync_openfile_t *of) {
pdbg_logf(D_NOTICE, "releasing file %s", of->currentname);
if (unlikely(of->writetimer != PSYNC_INVALID_TIMER))
@ -1770,7 +1776,7 @@ static void pfs_free_openfile(psync_openfile_t *of) {
}
close_if_valid(of->logfile);
ptree_for_each_element_call_safe(
of->sectorsinlog, psync_sector_inlog_t, tree, free);
of->sectorsinlog, psync_sector_inlog_t, tree, free_sector_inlog_node);
delete_log_files(of);
if (of->authenticatedints)
psync_interval_tree_free(of->authenticatedints);

View File

@ -2238,9 +2238,15 @@ int ppagecache_read_mod_locked(psync_openfile_t *of, char *buf,
return rd;
}
/* Free a psync_request_range_t node allocated via pmem_malloc. Used as the
* callback for psync_list_for_each_element_call when bulk-freeing the list. */
static void free_request_range(psync_request_range_t *range) {
pmem_free(PMEM_SUBSYS_CACHE, range);
}
static void psync_pagecache_free_request(psync_request_t *request) {
psync_list_for_each_element_call(&request->ranges, psync_request_range_t,
list, free);
list, free_request_range);
pmem_free(PMEM_SUBSYS_CACHE, request);
}