public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [syzbot] [fs?] [mm?] WARNING: bad unlock balance in hugetlb_vmdelete_list
@ 2025-09-23  9:03 syzbot
  2025-09-24 10:03 ` Forwarded: [PATCH] Fix a lock imbalance bug in hugetlb_vmdelete_list() that syzbot
  2025-09-25  6:23 ` Forwarded: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list syzbot
  0 siblings, 2 replies; 3+ messages in thread
From: syzbot @ 2025-09-23  9:03 UTC (permalink / raw)
  To: david, linux-fsdevel, linux-kernel, linux-mm, muchun.song,
	osalvador, syzkaller-bugs

Hello,

syzbot found the following issue on:

HEAD commit:    846bd2225ec3 Add linux-next specific files for 20250919
git tree:       linux-next
console output: https://syzkaller.appspot.com/x/log.txt?x=13263534580000
kernel config:  https://syzkaller.appspot.com/x/.config?x=135377594f35b576
dashboard link: https://syzkaller.appspot.com/bug?extid=62edf7e27b2e8f754525
compiler:       Debian clang version 20.1.8 (++20250708063551+0c9f909b7976-1~exp1~20250708183702.136), Debian LLD 20.1.8
syz repro:      https://syzkaller.appspot.com/x/repro.syz?x=14a118e2580000
C reproducer:   https://syzkaller.appspot.com/x/repro.c?x=17e204e2580000

Downloadable assets:
disk image: https://storage.googleapis.com/syzbot-assets/c53d48022f8a/disk-846bd222.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/483534e784c8/vmlinux-846bd222.xz
kernel image: https://storage.googleapis.com/syzbot-assets/721b36eec9b3/bzImage-846bd222.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com

=====================================
WARNING: bad unlock balance detected!
syzkaller #0 Not tainted
-------------------------------------
syz.0.8060/30977 is trying to release lock (&vma_lock->rw_sema) at:
[<ffffffff82903959>] hugetlb_vmdelete_list+0x179/0x1c0 fs/hugetlbfs/inode.c:501
but there are no more locks to release!

other info that might help us debug this:
3 locks held by syz.0.8060/30977:
 #0: ffff88807d8da420 (sb_writers#12){.+.+}-{0:0}, at: mnt_want_write+0x41/0x90 fs/namespace.c:508
 #1: ffff888034404648 (&sb->s_type->i_mutex_key#20){+.+.}-{4:4}, at: inode_lock_killable include/linux/fs.h:985 [inline]
 #1: ffff888034404648 (&sb->s_type->i_mutex_key#20){+.+.}-{4:4}, at: do_truncate+0x171/0x220 fs/open.c:63
 #2: ffff888034404918 (&hugetlbfs_i_mmap_rwsem_key){+.+.}-{4:4}, at: i_mmap_lock_write include/linux/fs.h:548 [inline]
 #2: ffff888034404918 (&hugetlbfs_i_mmap_rwsem_key){+.+.}-{4:4}, at: hugetlb_vmtruncate fs/hugetlbfs/inode.c:639 [inline]
 #2: ffff888034404918 (&hugetlbfs_i_mmap_rwsem_key){+.+.}-{4:4}, at: hugetlbfs_setattr+0x489/0x6d0 fs/hugetlbfs/inode.c:879

stack backtrace:
CPU: 1 UID: 0 PID: 30977 Comm: syz.0.8060 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025
Call Trace:
 <TASK>
 dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
 print_unlock_imbalance_bug+0xdc/0xf0 kernel/locking/lockdep.c:5298
 __lock_release kernel/locking/lockdep.c:5537 [inline]
 lock_release+0x269/0x3e0 kernel/locking/lockdep.c:5889
 up_write+0x2d/0x420 kernel/locking/rwsem.c:1642
 hugetlb_vmdelete_list+0x179/0x1c0 fs/hugetlbfs/inode.c:501
 hugetlb_vmtruncate fs/hugetlbfs/inode.c:641 [inline]
 hugetlbfs_setattr+0x4d1/0x6d0 fs/hugetlbfs/inode.c:879
 notify_change+0xc1a/0xf40 fs/attr.c:546
 do_truncate+0x1a4/0x220 fs/open.c:68
 handle_truncate fs/namei.c:3516 [inline]
 do_open fs/namei.c:3899 [inline]
 path_openat+0x306c/0x3830 fs/namei.c:4054
 do_filp_open+0x1fa/0x410 fs/namei.c:4081
 do_sys_openat2+0x121/0x1c0 fs/open.c:1435
 do_sys_open fs/open.c:1450 [inline]
 __do_sys_open fs/open.c:1458 [inline]
 __se_sys_open fs/open.c:1454 [inline]
 __x64_sys_open+0x11e/0x150 fs/open.c:1454
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fdea5b8eec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 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 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fdea6945038 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
RAX: ffffffffffffffda RBX: 00007fdea5de5fa0 RCX: 00007fdea5b8eec9
RDX: 0000000000000100 RSI: 000000000014927e RDI: 0000200000000340
RBP: 00007fdea5c11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fdea5de6038 R14: 00007fdea5de5fa0 R15: 00007ffe42e704f8
 </TASK>
------------[ cut here ]------------
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE)): count = 0x0, magic = 0xffff8880295a5408, owner = 0x1, curr 0xffff8880260d9e40, list empty
WARNING: kernel/locking/rwsem.c:1381 at __up_write kernel/locking/rwsem.c:1380 [inline], CPU#1: syz.0.8060/30977
WARNING: kernel/locking/rwsem.c:1381 at up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643, CPU#1: syz.0.8060/30977
Modules linked in:
CPU: 1 UID: 0 PID: 30977 Comm: syz.0.8060 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025
RIP: 0010:__up_write kernel/locking/rwsem.c:1380 [inline]
RIP: 0010:up_write+0x3a2/0x420 kernel/locking/rwsem.c:1643
Code: d0 48 c7 c7 00 f0 aa 8b 48 c7 c6 20 f2 aa 8b 48 8b 14 24 4c 89 f1 4d 89 e0 4c 8b 4c 24 08 41 52 e8 b3 39 e6 ff 48 83 c4 08 90 <0f> 0b 90 90 e9 6d fd ff ff 48 c7 c1 74 0b e5 8f 80 e1 07 80 c1 03
RSP: 0018:ffffc900051076c8 EFLAGS: 00010282
RAX: b37f99c54516e500 RBX: ffff8880295a5408 RCX: ffff8880260d9e40
RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000002
RBP: dffffc0000000000 R08: ffffc900051073e7 R09: 1ffff92000a20e7c
R10: dffffc0000000000 R11: fffff52000a20e7d R12: 0000000000000001
R13: ffff8880295a5460 R14: ffff8880295a5408 R15: 1ffff110052b4a82
FS:  00007fdea69456c0(0000) GS:ffff8881258a2000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fdea51fed58 CR3: 00000000779ba000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 hugetlb_vmdelete_list+0x179/0x1c0 fs/hugetlbfs/inode.c:501
 hugetlb_vmtruncate fs/hugetlbfs/inode.c:641 [inline]
 hugetlbfs_setattr+0x4d1/0x6d0 fs/hugetlbfs/inode.c:879
 notify_change+0xc1a/0xf40 fs/attr.c:546
 do_truncate+0x1a4/0x220 fs/open.c:68
 handle_truncate fs/namei.c:3516 [inline]
 do_open fs/namei.c:3899 [inline]
 path_openat+0x306c/0x3830 fs/namei.c:4054
 do_filp_open+0x1fa/0x410 fs/namei.c:4081
 do_sys_openat2+0x121/0x1c0 fs/open.c:1435
 do_sys_open fs/open.c:1450 [inline]
 __do_sys_open fs/open.c:1458 [inline]
 __se_sys_open fs/open.c:1454 [inline]
 __x64_sys_open+0x11e/0x150 fs/open.c:1454
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xfa/0xfa0 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fdea5b8eec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 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 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fdea6945038 EFLAGS: 00000246 ORIG_RAX: 0000000000000002
RAX: ffffffffffffffda RBX: 00007fdea5de5fa0 RCX: 00007fdea5b8eec9
RDX: 0000000000000100 RSI: 000000000014927e RDI: 0000200000000340
RBP: 00007fdea5c11f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007fdea5de6038 R14: 00007fdea5de5fa0 R15: 00007ffe42e704f8
 </TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Forwarded: [PATCH] Fix a lock imbalance bug in hugetlb_vmdelete_list() that
  2025-09-23  9:03 [syzbot] [fs?] [mm?] WARNING: bad unlock balance in hugetlb_vmdelete_list syzbot
@ 2025-09-24 10:03 ` syzbot
  2025-09-25  6:23 ` Forwarded: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list syzbot
  1 sibling, 0 replies; 3+ messages in thread
From: syzbot @ 2025-09-24 10:03 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] Fix a lock imbalance bug in hugetlb_vmdelete_list() that
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master

Fix a lock imbalance bug in hugetlb_vmdelete_list() that causes:
WARNING: bad unlock balance detected!
  hugetlb_vmdelete_list+0x179/0x1c0 is trying to release lock 
  (&vma_lock->rw_sema) but there are no more locks to release!

The issue is a race condition between multiple threads operating on the
same VMA:

1. Thread 1 calls hugetlb_vma_trylock_write() when vma->vm_private_data=NULL
2. trylock returns success (no lock needed for this VMA type)
3. Thread 2 allocates a lock structure: vma->vm_private_data=&new_lock
4. Thread 1 calls hugetlb_vma_unlock_write(), sees non-NULL vm_private_data
5. Thread 1 tries to unlock a lock it never acquired → crash

The fix is to save the VMA lock state at the time we make the locking
decision, rather than checking it again at unlock time. This prevents
the time-of-check-time-of-use (TOCTOU) race condition.

Reported-by: syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=62edf7e27b2e8f754525
Fixes: 8d9bfb2608cf ("hugetlb: add vma based lock for pmd sharing")
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hugetlbfs/inode.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9e0625167517..ae3e07eacd37 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -475,15 +475,16 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
 		      zap_flags_t zap_flags)
 {
 	struct vm_area_struct *vma;
-
 	/*
 	 * end == 0 indicates that the entire range after start should be
 	 * unmapped.  Note, end is exclusive, whereas the interval tree takes
 	 * an inclusive "last".
 	 */
 	vma_interval_tree_foreach(vma, root, start, end ? end - 1 : ULONG_MAX) {
+		struct hugetlb_vma_lock *vma_lock;
 		unsigned long v_start;
 		unsigned long v_end;
+		vma_lock = vma->vm_private_data;
 
 		if (!hugetlb_vma_trylock_write(vma))
 			continue;
@@ -498,7 +499,8 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
 		 * vmas.  Therefore, lock is not held when calling
 		 * unmap_hugepage_range for private vmas.
 		 */
-		hugetlb_vma_unlock_write(vma);
+		if (vma_lock)
+			hugetlb_vma_unlock_write(vma);
 	}
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Forwarded: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list
  2025-09-23  9:03 [syzbot] [fs?] [mm?] WARNING: bad unlock balance in hugetlb_vmdelete_list syzbot
  2025-09-24 10:03 ` Forwarded: [PATCH] Fix a lock imbalance bug in hugetlb_vmdelete_list() that syzbot
@ 2025-09-25  6:23 ` syzbot
  1 sibling, 0 replies; 3+ messages in thread
From: syzbot @ 2025-09-25  6:23 UTC (permalink / raw)
  To: linux-kernel, syzkaller-bugs

For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.

***

Subject: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list
Author: kartikey406@gmail.com

#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git master

hugetlb_vmdelete_list() has a lock imbalance bug where lock acquisition
and release evaluate VMA conditions at different times, potentially
causing unlock to be called on the wrong lock or skipped entirely.

The current code evaluates __vma_shareable_lock() and __vma_private_lock()
twice - once during hugetlb_vma_trylock_write() and again during
hugetlb_vma_unlock_write(). If VMA state changes between these calls
(due to unmap operations or concurrent access), the lock and unlock
paths may diverge, leading to:

1. Unlocking a lock that was never acquired
2. Unlocking the wrong lock type
3. Leaving a lock held

This manifests as "bad unlock balance detected" warnings:

  WARNING: bad unlock balance detected!
  trying to release lock (&vma_lock->rw_sema) at:
  hugetlb_vmdelete_list+0x179/0x1c0 fs/hugetlbfs/inode.c:501
  but there are no more locks to release!

Fix this by saving the lock type and pointer when acquiring the lock,
then using the saved information for unlock, ensuring symmetric lock
operations regardless of any VMA state changes.

Reported-by: syzbot+62edf7e27b2e8f754525@syzkaller.appspotmail.com
Link: https://syzkaller.appspot.com/bug?extid=62edf7e27b2e8f754525
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
 fs/hugetlbfs/inode.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9e0625167517..2721ba2ee3f3 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -42,6 +42,10 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/hugetlbfs.h>
 
+#define HPAGE_RESV_OWNER    (1UL << 0)
+#define HPAGE_RESV_UNMAPPED (1UL << 1)
+#define HPAGE_RESV_MASK (HPAGE_RESV_OWNER | HPAGE_RESV_UNMAPPED)
+
 static const struct address_space_operations hugetlbfs_aops;
 static const struct file_operations hugetlbfs_file_operations;
 static const struct inode_operations hugetlbfs_dir_inode_operations;
@@ -475,6 +479,9 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
 		      zap_flags_t zap_flags)
 {
 	struct vm_area_struct *vma;
+	struct hugetlb_vma_lock *vma_lock;
+	struct resv_map *resv_map;
+	bool locked;
 
 	/*
 	 * end == 0 indicates that the entire range after start should be
@@ -484,8 +491,24 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
 	vma_interval_tree_foreach(vma, root, start, end ? end - 1 : ULONG_MAX) {
 		unsigned long v_start;
 		unsigned long v_end;
-
-		if (!hugetlb_vma_trylock_write(vma))
+		vma_lock = NULL;
+		resv_map = NULL;
+		locked = false;
+
+		if (__vma_shareable_lock(vma)) {
+			vma_lock = vma->vm_private_data;
+			if (vma_lock && down_write_trylock(&vma_lock->rw_sema))
+				locked = true;
+		} else if (__vma_private_lock(vma)) {
+			resv_map = (struct resv_map *)((unsigned long)vma->vm_private_data & ~HPAGE_RESV_MASK);
+			if (resv_map && down_write_trylock(&resv_map->rw_sema))
+				locked = true;
+		} else {
+			/* No lock needed for this VMA */
+			locked = true;
+		}
+
+		if (!locked)
 			continue;
 
 		v_start = vma_offset_start(vma, start);
@@ -498,7 +521,10 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end,
 		 * vmas.  Therefore, lock is not held when calling
 		 * unmap_hugepage_range for private vmas.
 		 */
-		hugetlb_vma_unlock_write(vma);
+		if (vma_lock)
+			up_write(&vma_lock->rw_sema);
+		else if (resv_map)
+			up_write(&resv_map->rw_sema);
 	}
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-09-25  6:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-23  9:03 [syzbot] [fs?] [mm?] WARNING: bad unlock balance in hugetlb_vmdelete_list syzbot
2025-09-24 10:03 ` Forwarded: [PATCH] Fix a lock imbalance bug in hugetlb_vmdelete_list() that syzbot
2025-09-25  6:23 ` Forwarded: [PATCH] hugetlbfs: fix lock imbalance in hugetlb_vmdelete_list syzbot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox