lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <20251024144332.33773-2-nirbhay.lkd@gmail.com>
Date: Fri, 24 Oct 2025 20:13:33 +0530
From: Nirbhay Sharma <nirbhay.lkd@...il.com>
To: Andreas Gruenbacher <agruenba@...hat.com>
Cc: gfs2@...ts.linux.dev,
	linux-kernel@...r.kernel.org,
	syzbot+19e0be39cc25dfcb0858@...kaller.appspotmail.com,
	skhan@...uxfoundation.org,
	david.hunter.linux@...il.com,
	linux-kernel-mentees@...ts.linuxfoundation.org,
	Nirbhay Sharma <nirbhay.lkd@...il.com>
Subject: [PATCH] gfs2: flush withdraw work before freeing gfs2_sbd

Syzbot reported an ODEBUG warning where free_sbd() was freeing memory
containing an active work_struct (sd_withdraw_work):

  ODEBUG: free active (active state 0) object: ffff888026c285a0
  object type: work_struct hint: gfs2_withdraw_func+0x0/0x430
  WARNING: CPU: 0 PID: 6010 at lib/debugobjects.c:545
  Call Trace:
   free_sbd+0x1e4/0x270 fs/gfs2/ops_fstype.c:1308

The issue occurs when gfs2_fill_super() fails after initializing
sd_withdraw_work at line 1218. Some error paths (fail_lm, fail_debug,
etc.) skip the existing flush_work() at the fail_inodes label and jump
directly to fail_free, which calls free_sbd() without flushing the
potentially pending work.

free_sbd() is also called from init_sbd()'s error path before
sd_withdraw_work is initialized. Since the structure is allocated with
kzalloc(), work.func is NULL in this case.

Fix by adding a guarded flush_work() to free_sbd(). Check work.func
before flushing to handle both cases: when called after INIT_WORK()
(work must be flushed), and when called before INIT_WORK() (work.func
is NULL, skip flushing). This avoids the WARN_ON(!work->func) in
__flush_work().

Note: gfs2_put_super() already calls flush_work() before free_sbd()
(line 606), so the flush in free_sbd() will be redundant but harmless
for the normal unmount path.

Reported-by: syzbot+19e0be39cc25dfcb0858@...kaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=19e0be39cc25dfcb0858
Fixes: 8fdd8a28fe5c ("gfs2: Asynchronous withdraw")
Signed-off-by: Nirbhay Sharma <nirbhay.lkd@...il.com>
---
Testing performed:
- Reproduced original bug with syzbot C reproducer
- Verified fix prevents ODEBUG warnings in all error paths
- Tested early mount failures (unformatted devices)
- Tested all gfs2_fill_super error paths (4 scenarios)
- Parallel mount stress test (3 concurrent operations)
- Memory leak test (50 mount/unmount cycles, <4MB variance)
- Race condition testing passed
- Validated with syzbot on linux-next (Oct 22)
- All tests completed with zero ODEBUG warnings

 fs/gfs2/ops_fstype.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index 08502d967e71..6cea03410e57 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -67,6 +67,14 @@ void free_sbd(struct gfs2_sbd *sdp)
 {
 	struct super_block *sb = sdp->sd_vfs;
 
+	/*
+	 * Only flush withdraw work if initialized. Work is initialized in
+	 * gfs2_fill_super() at line 1218, after init_sbd() succeeds.
+	 * Checking func avoids WARN_ON in __flush_work() for early failures.
+	 */
+	if (sdp->sd_withdraw_work.func)
+		flush_work(&sdp->sd_withdraw_work);
+
 	free_percpu(sdp->sd_lkstats);
 	sb->s_fs_info = NULL;
 	kfree(sdp);
-- 
2.48.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ