summaryrefslogtreecommitdiff
path: root/fs/jfs
diff options
context:
space:
mode:
authorHelen Koike <koike@igalia.com>2026-02-27 15:11:50 -0300
committerDave Kleikamp <dave.kleikamp@oracle.com>2026-03-11 10:57:52 -0500
commitca5848ae87d24886a7886f5a22278bd4045c15f8 (patch)
tree2febb79e7e3857fe928feed921cdd5777ba3a07a /fs/jfs
parentb15e4310633f90072d66cc9b6692acbf6b4d7d00 (diff)
downloadlinux-next-ca5848ae87d24886a7886f5a22278bd4045c15f8.tar.gz
linux-next-ca5848ae87d24886a7886f5a22278bd4045c15f8.zip
jfs: hold LOG_LOCK on umount to avoid null-ptr-deref
write_special_inodes() function iterate through the log->sb_list and access the sbi fields, which can be set to NULL concurrently by umount. Fix concurrency issue by holding LOG_LOCK and checking for NULL. Reported-by: syzbot+e14b1036481911ae4d77@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=e14b1036481911ae4d77 Signed-off-by: Helen Koike <koike@igalia.com> Signed-off-by: Dave Kleikamp <dave.kleikamp@oracle.com>
Diffstat (limited to 'fs/jfs')
-rw-r--r--fs/jfs/jfs_logmgr.c16
-rw-r--r--fs/jfs/jfs_logmgr.h7
-rw-r--r--fs/jfs/jfs_umount.c10
3 files changed, 24 insertions, 9 deletions
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 472b6500e817..306165e61438 100644
--- a/fs/jfs/jfs_logmgr.c
+++ b/fs/jfs/jfs_logmgr.c
@@ -74,12 +74,6 @@ static struct lbuf *log_redrive_list;
static DEFINE_SPINLOCK(log_redrive_lock);
-/*
- * log read/write serialization (per log)
- */
-#define LOG_LOCK_INIT(log) mutex_init(&(log)->loglock)
-#define LOG_LOCK(log) mutex_lock(&((log)->loglock))
-#define LOG_UNLOCK(log) mutex_unlock(&((log)->loglock))
/*
@@ -204,9 +198,13 @@ static void write_special_inodes(struct jfs_log *log,
struct jfs_sb_info *sbi;
list_for_each_entry(sbi, &log->sb_list, log_list) {
- writer(sbi->ipbmap->i_mapping);
- writer(sbi->ipimap->i_mapping);
- writer(sbi->direct_inode->i_mapping);
+ /* These pointers can be NULL before list_del during umount */
+ if (sbi->ipbmap)
+ writer(sbi->ipbmap->i_mapping);
+ if (sbi->ipimap)
+ writer(sbi->ipimap->i_mapping);
+ if (sbi->direct_inode)
+ writer(sbi->direct_inode->i_mapping);
}
}
diff --git a/fs/jfs/jfs_logmgr.h b/fs/jfs/jfs_logmgr.h
index 8b8994e48cd0..09e0ef6aecce 100644
--- a/fs/jfs/jfs_logmgr.h
+++ b/fs/jfs/jfs_logmgr.h
@@ -403,6 +403,13 @@ struct jfs_log {
};
/*
+ * log read/write serialization (per log)
+ */
+#define LOG_LOCK_INIT(log) mutex_init(&(log)->loglock)
+#define LOG_LOCK(log) mutex_lock(&((log)->loglock))
+#define LOG_UNLOCK(log) mutex_unlock(&((log)->loglock))
+
+/*
* Log flag
*/
#define log_INLINELOG 1
diff --git a/fs/jfs/jfs_umount.c b/fs/jfs/jfs_umount.c
index 8ec43f53f686..18569f1eaabd 100644
--- a/fs/jfs/jfs_umount.c
+++ b/fs/jfs/jfs_umount.c
@@ -20,6 +20,7 @@
#include "jfs_superblock.h"
#include "jfs_dmap.h"
#include "jfs_imap.h"
+#include "jfs_logmgr.h"
#include "jfs_metapage.h"
#include "jfs_debug.h"
@@ -58,6 +59,12 @@ int jfs_umount(struct super_block *sb)
jfs_flush_journal(log, 2);
/*
+ * Hold log lock so write_special_inodes (lmLogSync) cannot see
+ * this sbi with a NULL inode pointer while iterating log->sb_list.
+ */
+ if (log)
+ LOG_LOCK(log);
+ /*
* close fileset inode allocation map (aka fileset inode)
*/
diUnmount(ipimap, 0);
@@ -95,6 +102,9 @@ int jfs_umount(struct super_block *sb)
*/
filemap_write_and_wait(sbi->direct_inode->i_mapping);
+ if (log)
+ LOG_UNLOCK(log);
+
/*
* ensure all file system file pages are propagated to their
* home blocks on disk (and their in-memory buffer pages are