From a94cf561fb8cb29cc84b41cf0064ecb634a5f04d Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sun, 22 Mar 2026 15:32:50 +0100 Subject: [PATCH] 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 --- pclsync/pfs.c | 8 +++++++- pclsync/ppagecache.c | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/pclsync/pfs.c b/pclsync/pfs.c index 02b3c18..f68f6b9 100644 --- a/pclsync/pfs.c +++ b/pclsync/pfs.c @@ -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); diff --git a/pclsync/ppagecache.c b/pclsync/ppagecache.c index d115b3f..96d16eb 100644 --- a/pclsync/ppagecache.c +++ b/pclsync/ppagecache.c @@ -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); }