* [PATCH] hugetlb: supports unmapping private mappings [not found] <6adf3170.a6443767.132891.0077.GAE@google.com> @ 2026-10-28 4:15 ` Edward Adam Davis 2026-10-28 14:14 ` [syzbot ci] " syzbot ci 0 siblings, 1 reply; 2+ messages in thread From: Edward Adam Davis @ 2026-10-28 4:15 UTC (permalink / raw) To: syzbot+2fcec0eca7f4cade53b2 Cc: muchun.song, osalvador, mike.kravetz, linux-mm, linux-kernel, syzkaller-bugs If a file has a private mapping, then truncating the file's original logic will only unmap it according to the shared mapping method, potentially hitting: refcount_t: addition on 0; use-after-free. kernel BUG at lib/refcount.c:34! RIP: 0010:refcount_warn_saturate+0xf0/0x110 lib/refcount.c:34 Call Trace: kref_get include/linux/kref.h:45 [inline] hugetlb_unmap_file_folio fs/hugetlbfs/inode.c:413 [inline] remove_inode_single_folio fs/hugetlbfs/inode.c:512 [inline] remove_inode_hugepages+0xbdb/0x10f0 fs/hugetlbfs/inode.c:577 hugetlb_vmtruncate fs/hugetlbfs/inode.c:621 [inline] hugetlbfs_setattr+0x4f0/0x6d0 fs/hugetlbfs/inode.c:856 notify_change+0xbb8/0xec0 fs/attr.c:556 do_truncate+0x1c2/0x250 fs/open.c:68 Add logic to handle the unmapping of private mappings. Fixes: 40549ba8f8e0 ("hugetlb: use new vma_lock for pmd sharing synchronization") Reported-by: syzbot+2fcec0eca7f4cade53b2@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=2fcec0eca7f4cade53b2 Signed-off-by: Edward Adam Davis <eadavis@sina.com> --- fs/hugetlbfs/inode.c | 58 +++++++++++++++++++++++++---------------- include/linux/hugetlb.h | 6 +++++ mm/hugetlb.c | 3 +-- 3 files changed, 43 insertions(+), 24 deletions(-) diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 6656807ce437..166183b7ee36 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -382,6 +382,7 @@ static void hugetlb_unmap_file_folio(struct hstate *h, struct folio *folio, pgoff_t index) { struct hugetlb_vma_lock *vma_lock; + struct resv_map *resv_map; unsigned long pfn = folio_pfn(folio); struct vm_area_struct *vma; unsigned long v_start; @@ -394,6 +395,7 @@ static void hugetlb_unmap_file_folio(struct hstate *h, i_mmap_lock_write(mapping); retry: vma_lock = NULL; + resv_map = NULL; mapping_rmap_tree_foreach(vma, mapping, start, end - 1) { v_start = vma_offset_start(vma, start); v_end = vma_offset_end(vma, end); @@ -402,15 +404,21 @@ static void hugetlb_unmap_file_folio(struct hstate *h, continue; if (!hugetlb_vma_trylock_write(vma)) { - vma_lock = vma->vm_private_data; - /* - * If we can not get vma lock, we need to drop - * immap_sema and take locks in order. First, - * take a ref on the vma_lock structure so that - * we can be guaranteed it will not go away when - * dropping immap_sema. - */ - kref_get(&vma_lock->refs); + if (vma->vm_flags & VM_MAYSHARE) { + vma_lock = vma->vm_private_data; + /* + * If we can not get vma lock, we need to drop + * immap_sema and take locks in order. First, + * take a ref on the vma_lock structure so that + * we can be guaranteed it will not go away when + * dropping immap_sema. + */ + kref_get(&vma_lock->refs); + } else { + resv_map = vma_resv_map(vma); + kref_get(&resv_map->refs); + } + break; } @@ -421,25 +429,28 @@ static void hugetlb_unmap_file_folio(struct hstate *h, i_mmap_unlock_write(mapping); - if (vma_lock) { + if (vma_lock || resv_map) { /* * Wait on vma_lock. We know it is still valid as we have * a reference. We must 'open code' vma locking as we do * not know if vma_lock is still attached to vma. */ - down_write(&vma_lock->rw_sema); + hugetlb_vma_lock_write(vma); i_mmap_lock_write(mapping); - vma = vma_lock->vma; - if (!vma) { - /* - * If lock is no longer attached to vma, then just - * unlock, drop our reference and retry looking for - * other vmas. - */ - up_write(&vma_lock->rw_sema); - kref_put(&vma_lock->refs, hugetlb_vma_lock_release); - goto retry; + if (vma_lock) { + vma = vma_lock->vma; + if (!vma) { + /* + * If lock is no longer attached to vma, then + * just unlock, drop our reference and retry + * looking for other vmas. + */ + up_write(&vma_lock->rw_sema); + kref_put(&vma_lock->refs, + hugetlb_vma_lock_release); + goto retry; + } } /* @@ -452,7 +463,10 @@ static void hugetlb_unmap_file_folio(struct hstate *h, unmap_hugepage_range(vma, v_start, v_end, NULL, ZAP_FLAG_DROP_MARKER); - kref_put(&vma_lock->refs, hugetlb_vma_lock_release); + if (vma_lock) + kref_put(&vma_lock->refs, hugetlb_vma_lock_release); + else + kref_put(&resv_map->refs, resv_map_release); hugetlb_vma_unlock_write(vma); goto retry; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 80a5a03e9cee..f980191c651b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -268,6 +268,7 @@ void hugetlb_vma_unlock_read(struct vm_area_struct *vma); void hugetlb_vma_lock_write(struct vm_area_struct *vma); void hugetlb_vma_unlock_write(struct vm_area_struct *vma); int hugetlb_vma_trylock_write(struct vm_area_struct *vma); +struct resv_map *vma_resv_map(struct vm_area_struct *vma); void hugetlb_vma_assert_locked(struct vm_area_struct *vma); void hugetlb_vma_lock_release(struct kref *kref); long hugetlb_change_protection(struct vm_area_struct *vma, @@ -392,6 +393,11 @@ static inline int is_hugepage_only_range(struct mm_struct *mm, return 0; } +static inline struct resv_map *vma_resv_map(struct vm_area_struct *vma) +{ + return NULL; +} + #ifdef CONFIG_USERFAULTFD static inline int hugetlb_mfill_atomic_pte(pte_t *dst_pte, struct vm_area_struct *dst_vma, diff --git a/mm/hugetlb.c b/mm/hugetlb.c index b017ae1dfd6f..def6aebc44fd 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -134,7 +134,6 @@ static int __huge_pmd_unshare(struct mmu_gather *tlb, bool check_locks); static void hugetlb_unshare_pmds(struct vm_area_struct *vma, unsigned long start, unsigned long end, bool take_locks); -static struct resv_map *vma_resv_map(struct vm_area_struct *vma); static inline bool subpool_is_free(struct hugepage_subpool *spool) { @@ -1145,7 +1144,7 @@ static inline struct resv_map *inode_resv_map(struct inode *inode) return HUGETLBFS_I(inode)->resv_map; } -static struct resv_map *vma_resv_map(struct vm_area_struct *vma) +struct resv_map *vma_resv_map(struct vm_area_struct *vma) { VM_BUG_ON_VMA(!is_vm_hugetlb_page(vma), vma); if (vma->vm_flags & VM_MAYSHARE) { -- 2.43.0 ^ permalink raw reply related [flat|nested] 2+ messages in thread
* [syzbot ci] Re: hugetlb: supports unmapping private mappings 2026-10-28 4:15 ` [PATCH] hugetlb: supports unmapping private mappings Edward Adam Davis @ 2026-10-28 14:14 ` syzbot ci 0 siblings, 0 replies; 2+ messages in thread From: syzbot ci @ 2026-10-28 14:14 UTC (permalink / raw) To: eadavis, linux-kernel, linux-mm, mike.kravetz, muchun.song, osalvador, syzbot, syzkaller-bugs Cc: syzbot, syzkaller-bugs syzbot ci has tested the following series [v1] hugetlb: supports unmapping private mappings https://lore.kernel.org/all/20261028041528.269829-1-eadavis@sina.com * [PATCH] hugetlb: supports unmapping private mappings and found the following issue: WARNING: bad unlock balance in remove_inode_hugepages Full report is available here: https://ci.syzbot.org/series/bf349aec-df0c-48a8-ab82-9f71361a3830 *** WARNING: bad unlock balance in remove_inode_hugepages tree: mm-new URL: https://kernel.googlesource.com/pub/scm/linux/kernel/git/akpm/mm.git base: 7d1f84f1b94e79cb95d974ab3ec54cb3a4d64f5b arch: amd64 compiler: Debian clang version 22.1.8 (1~deb13u4), Debian LLD 22.1.8 config: https://ci.syzbot.org/builds/7d19c5c0-63db-4726-978e-d863eedfb488/config ===================================== WARNING: bad unlock balance detected! syzkaller #0 Not tainted ------------------------------------- syz.4.862/12304 is trying to release lock (&vma_lock->rw_sema) at: [<ffffffff82b5a0e7>] remove_inode_hugepages+0xc57/0x1220 but there are no more locks to release! other info that might help us debug this: locks held by syz.4.862/12304: 4, last CPU#1: #0: ffff88810729e460 (sb_writers#12){.+.+}-{0:0}, at: vfs_fallocate+0x5e0/0x7e0 #1: ffff8881aa537b00 (&sb->s_type->i_mutex_key#24){+.+.}-{4:4}, at: hugetlbfs_fallocate+0x3f7/0x11c0 #2: ffff8881683dc638 (&hugetlb_fault_mutex_table[i]){+.+.}-{4:4}, at: remove_inode_hugepages+0x370/0x1220 #3: ffff8881aa537da8 (&hugetlbfs_i_mmap_rwsem_key){+.+.}-{4:4}, at: remove_inode_hugepages+0xa44/0x1220 stack backtrace: CPU: 1 UID: 0 PID: 12304 Comm: syz.4.862 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0xe8/0x150 print_unlock_imbalance_bug+0xdc/0xf0 lock_release+0x252/0x3c0 up_write+0x2d/0x4a0 remove_inode_hugepages+0xc57/0x1220 hugetlbfs_fallocate+0xc51/0x11c0 vfs_fallocate+0x65a/0x7e0 madvise_vma_behavior+0x2cf5/0x43b0 madvise_walk_vmas+0x576/0xb00 madvise_do_behavior+0x385/0x540 do_madvise+0x327/0x3a0 __x64_sys_madvise+0xa6/0xc0 do_syscall_64+0x166/0x520 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f0c8dd9f559 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f0c8bff6028 EFLAGS: 00000246 ORIG_RAX: 000000000000001c RAX: ffffffffffffffda RBX: 00007f0c8e026450 RCX: 00007f0c8dd9f559 RDX: 0000000000000009 RSI: 0000000000c00000 RDI: 0000200000400000 RBP: 00007f0c8de36b20 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007f0c8e0264e8 R14: 00007f0c8e026450 R15: 00007ffc9fc94698 </TASK> ------------[ cut here ]------------ DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff88810b4c2608, owner = 0x0, curr 0xffff88816ff4bc00, list not empty WARNING: kernel/locking/rwsem.c:1413 at up_write+0x35c/0x4a0, CPU#1: syz.4.862/12304 Modules linked in: CPU: 1 UID: 0 PID: 12304 Comm: syz.4.862 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014 RIP: 0010:up_write+0x40f/0x4a0 Code: 0d 8c 49 c7 c2 80 33 0d 8c 4c 0f 44 d0 48 8b 7c 24 10 48 c7 c6 20 36 0d 8c 48 8b 14 24 48 8b 4c 24 08 4d 89 e0 4d 89 f9 41 52 <67> 48 0f b9 3a 48 83 c4 08 e8 f3 6f 45 03 e9 d6 fc ff ff 48 c7 c1 RSP: 0018:ffffc900040cede0 EFLAGS: 00010246 RAX: ffffffff8c0d33a0 RBX: ffff88810b4c2608 RCX: ffff88810b4c2608 RDX: 0000000000000000 RSI: ffffffff8c0d3620 RDI: ffffffff917dda70 RBP: dffffc0000000000 R08: 0000000000000000 R09: ffff88816ff4bc00 R10: ffffffff8c0d33a0 R11: ffffed10216984c3 R12: 0000000000000000 R13: ffff88810b4c2610 R14: ffff88810b4c2660 R15: ffff88816ff4bc00 FS: 00007f0c8bff66c0(0000) GS:ffff8882a7c83000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f8981484378 CR3: 00000001ad2de000 CR4: 00000000000006f0 Call Trace: <TASK> remove_inode_hugepages+0xc57/0x1220 hugetlbfs_fallocate+0xc51/0x11c0 vfs_fallocate+0x65a/0x7e0 madvise_vma_behavior+0x2cf5/0x43b0 madvise_walk_vmas+0x576/0xb00 madvise_do_behavior+0x385/0x540 do_madvise+0x327/0x3a0 __x64_sys_madvise+0xa6/0xc0 do_syscall_64+0x166/0x520 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f0c8dd9f559 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f0c8bff6028 EFLAGS: 00000246 ORIG_RAX: 000000000000001c RAX: ffffffffffffffda RBX: 00007f0c8e026450 RCX: 00007f0c8dd9f559 RDX: 0000000000000009 RSI: 0000000000c00000 RDI: 0000200000400000 RBP: 00007f0c8de36b20 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007f0c8e0264e8 R14: 00007f0c8e026450 R15: 00007ffc9fc94698 </TASK> *** If these findings have caused you to resend the series or submit a separate fix, please add the following tag to your commit message: Tested-by: syzbot@syzkaller.appspotmail.com --- This report is generated by a bot. It may contain errors. syzbot ci engineers can be reached at syzkaller@googlegroups.com. To test a fix for this bug, please reply with `#syz test` (on a separate line) and attach the patch to the email. Notes: - The patch will be applied on top of the tested series (as an incremental fix). - To test a new version of the whole series, please send it directly to syzbot@lists.linux.dev. - Arguments like custom git repos and branches are not supported. ^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-28 14:14 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <6adf3170.a6443767.132891.0077.GAE@google.com>
2026-10-28 4:15 ` [PATCH] hugetlb: supports unmapping private mappings Edward Adam Davis
2026-10-28 14:14 ` [syzbot ci] " syzbot ci
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox