From 29e78760a5e0eface406ea87ad6dd91400d0dc6c Mon Sep 17 00:00:00 2001 From: dujunbao <14829755+du-junbao@user.noreply.gitee.com> Date: Tue, 22 Sep 2026 22:04:28 +0800 Subject: [PATCH] ub: obmm: only count the ownership of cacheable mappings obmm_vma_close() drops the per-page read/write counts of the region for every mapping, but only a cacheable ("normal") mapping ever added to them: obmm_mmap() runs init_ownership_info() and the matching update_vma_perm_count() on the cacheable path, while a mapping created with O_SYNC on a cc region only calls map_obmm_region(). A region can therefore take this sequence: cacheable mmap and munmap (counts back to zero, mmap_mode reset to INIT, ownership info kept), then an O_SYNC mmap, which is allowed from INIT, and its munmap. That last close decrements counters that were never incremented. The counts are uint16_t and update_page_ownership() has no lower bound, so they wrap to 65535, and the ownership accounting of the region - which decides the cache flush operations - stays wrong for the rest of its life. Only touch the counts while the region is in the cacheable mapping mode, which is also the mode that created them. Fixes: 7697ccb77f45 ("obmm: refactor ownership tracking for PMD-granularity support") --- drivers/ub/obmm/obmm_shm_dev.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/ub/obmm/obmm_shm_dev.c b/drivers/ub/obmm/obmm_shm_dev.c index e70792673a80..56b61926242a 100644 --- a/drivers/ub/obmm/obmm_shm_dev.c +++ b/drivers/ub/obmm/obmm_shm_dev.c @@ -48,7 +48,17 @@ static void obmm_vma_close(struct vm_area_struct *vma) mutex_lock(®->state_mutex); - cache_ops = update_vma_perm_count(reg, region_pgoff, npages, access, OBMM_SHM_MEM_NO_ACCESS); + /* + * Only the cacheable mappings take part in the ownership counters: + * an O_SYNC mapping of a cc region was mapped without counting it, + * so it must not decrement the counters on the way out. The mode is + * INIT only while no mapping exists, and a region cannot be mapped + * cacheable and non-cacheable at the same time. + */ + cache_ops = OBMM_SHM_CACHE_NONE; + if (reg->mmap_mode == OBMM_MMAP_NORMAL) + cache_ops = update_vma_perm_count(reg, region_pgoff, npages, + access, OBMM_SHM_MEM_NO_ACCESS); if (cache_ops != OBMM_SHM_CACHE_NONE && reg->mmap_mode == OBMM_MMAP_NORMAL) { ret = obmm_region_flush_range(reg, region_pgoff << PAGE_SHIFT, -- Gitee