From e40e88e431d49db4301bf216adedc3db64931ced Mon Sep 17 00:00:00 2001 From: fullex <0xfullex@gmail.com> Date: Tue, 6 Jan 2026 14:19:11 +0800 Subject: [PATCH] fix(section_list): add spinlock for free list and fix use-after-unmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add pthread_spinlock to protect pop_free_article_block() and push_free_article_block() operations from race conditions - Initialize spinlock in article_block_init() - Destroy spinlock in detach_article_block_shm() - Fix use-after-unmap in detach_article_block_shm() by saving shm_count and shm_size before unmapping the pool 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/section_list.c | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/section_list.c b/src/section_list.c index cf7f468..6f4cc07 100644 --- a/src/section_list.c +++ b/src/section_list.c @@ -16,6 +16,7 @@ #include "user_list.h" #include #include +#include #include #include #include @@ -78,6 +79,9 @@ typedef struct article_block_pool_t ARTICLE_BLOCK_POOL; static char article_block_shm_name[FILE_NAME_LEN]; static ARTICLE_BLOCK_POOL *p_article_block_pool = NULL; +/* Spinlock for protecting free list operations */ +static pthread_spinlock_t free_list_spinlock; + static char section_list_shm_name[FILE_NAME_LEN]; SECTION_LIST_POOL *p_section_list_pool = NULL; @@ -102,6 +106,13 @@ int article_block_init(const char *filename, int block_count) return -1; } + /* Initialize spinlock for free list protection */ + if (pthread_spin_init(&free_list_spinlock, PTHREAD_PROCESS_PRIVATE) != 0) + { + log_error("pthread_spin_init error"); + return -1; + } + if (block_count <= 0 || block_count > ARTICLE_BLOCK_PER_POOL) { log_error("article_block_count exceed limit %d", ARTICLE_BLOCK_PER_POOL); @@ -281,12 +292,19 @@ int set_article_block_shm_readonly(void) int detach_article_block_shm(void) { + int shm_count; + size_t pool_shm_size; + if (p_article_block_pool == NULL) { return -1; } - for (int i = 0; i < p_article_block_pool->shm_count; i++) + /* Save necessary data before unmapping to avoid use-after-unmap */ + shm_count = p_article_block_pool->shm_count; + pool_shm_size = p_article_block_pool->shm_size; + + for (int i = 0; i < shm_count; i++) { if ((p_article_block_pool->shm_pool + i)->p_shm != NULL && munmap((p_article_block_pool->shm_pool + i)->p_shm, (p_article_block_pool->shm_pool + i)->shm_size) < 0) @@ -296,7 +314,7 @@ int detach_article_block_shm(void) } } - if (p_article_block_pool != NULL && munmap(p_article_block_pool, p_article_block_pool->shm_size) < 0) + if (p_article_block_pool != NULL && munmap(p_article_block_pool, pool_shm_size) < 0) { log_error("munmap() error (%d)", errno); return -3; @@ -304,6 +322,9 @@ int detach_article_block_shm(void) p_article_block_pool = NULL; + /* Destroy spinlock */ + pthread_spin_destroy(&free_list_spinlock); + return 0; } @@ -311,6 +332,8 @@ inline static ARTICLE_BLOCK *pop_free_article_block(void) { ARTICLE_BLOCK *p_block = NULL; + pthread_spin_lock(&free_list_spinlock); + if (p_article_block_pool->p_block_free_list != NULL) { p_block = p_article_block_pool->p_block_free_list; @@ -319,13 +342,19 @@ inline static ARTICLE_BLOCK *pop_free_article_block(void) p_block->article_count = 0; } + pthread_spin_unlock(&free_list_spinlock); + return p_block; } inline static void push_free_article_block(ARTICLE_BLOCK *p_block) { + pthread_spin_lock(&free_list_spinlock); + p_block->p_next_block = p_article_block_pool->p_block_free_list; p_article_block_pool->p_block_free_list = p_block; + + pthread_spin_unlock(&free_list_spinlock); } int article_block_reset(void)