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] [thread-next>] [day] [month] [year] [list]
Message-ID: <tencent_7C86DFB364837BA979A3B0A44CF768577205@qq.com>
Date: Tue, 15 Oct 2024 12:50:05 +0800
From: Edward Adam Davis <eadavis@...com>
To: guohui.study@...il.com
Cc: brauner@...nel.org,
	jack@...e.cz,
	jfs-discussion@...ts.sourceforge.net,
	linux-kernel@...r.kernel.org,
	lizhi.xu@...driver.com,
	shaggy@...nel.org,
	syzkaller-bugs@...glegroups.com,
	willy@...radead.org
Subject: [PATCH] jfs: Fix null-ptr-deref in write_special_inodes

There is a race condition when accessing ipimap and ipbmap.

        CPU1                              CPU2
	====                              ====
	jfs_umount
	sbi->ipimap = NULL;               lmLogSync
	sbi->ipbmap = NULL;               write_special_inodes
	lmLogClose			  writer(sbi->ipbmap->i_mapping);
					  writer(sbi->ipimap->i_mapping);

The jfs umount and lmLogSync compete to access ipimap and ipbmap, resulting in
null pointer access to ipimap and ipbmap when executing write_special_inodes.

We can fix it by first closing the log in jfs umount, and then releasing
ipimap/ipbmap.

Reported-by: Hui Guo<guohui.study@...il.com>
Link: https://lore.kernel.org/all/CAHOo4gKf2mjPX8oAxCBUc74=+OToMdu6pe6iALGCOmXjToFaKw@mail.gmail.com/
Signed-off-by: Edward Adam Davis <eadavis@...com>
---
 fs/jfs/jfs_umount.c | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 8ec43f53f686..c5fda516ca85 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -42,7 +42,7 @@ int jfs_umount(struct super_block *sb)
 	struct inode *ipaimap = sbi->ipaimap;
 	struct inode *ipaimap2 = sbi->ipaimap2;
 	struct jfs_log *log;
-	int rc = 0;
+	int rc = 0, sb_update = 0;
 
 	jfs_info("UnMount JFS: sb:0x%p", sb);
 
@@ -51,11 +51,19 @@ int jfs_umount(struct super_block *sb)
 	 *
 	 * if mounted read-write and log based recovery was enabled
 	 */
-	if ((log = sbi->log))
+	if ((log = sbi->log)) {
 		/*
 		 * Wait for outstanding transactions to be written to log:
 		 */
 		jfs_flush_journal(log, 2);
+		/*
+		 * close log:
+		 *
+		 * remove file system from log active file system list.
+		 */
+		rc = lmLogClose(sb);
+		sb_update = 1;
+	}
 
 	/*
 	 * close fileset inode allocation map (aka fileset inode)
@@ -103,15 +111,8 @@ int jfs_umount(struct super_block *sb)
 	 * consistent state) and log superblock active file system
 	 * list (to signify skip logredo()).
 	 */
-	if (log) {		/* log = NULL if read-only mount */
+	if (sb_update) {		/* log = NULL if read-only mount */
 		updateSuper(sb, FM_CLEAN);
-
-		/*
-		 * close log:
-		 *
-		 * remove file system from log active file system list.
-		 */
-		rc = lmLogClose(sb);
 	}
 	jfs_info("UnMount JFS Complete: rc = %d", rc);
 	return rc;
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ