fs/jfs/jfs_logmgr.c | 16 +++++++--------- fs/jfs/jfs_logmgr.h | 7 +++++++ fs/jfs/jfs_umount.c | 10 ++++++++++ 3 files changed, 24 insertions(+), 9 deletions(-)
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>
---
fs/jfs/jfs_logmgr.c | 16 +++++++---------
fs/jfs/jfs_logmgr.h | 7 +++++++
fs/jfs/jfs_umount.c | 10 ++++++++++
3 files changed, 24 insertions(+), 9 deletions(-)
diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
index 5b1c5da04163..59f94c28007d 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
@@ -402,6 +402,13 @@ struct jfs_log {
int no_integrity; /* 3: flag to disable journaling to disk */
};
+/*
+ * 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
*/
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"
@@ -57,6 +58,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)
*/
@@ -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
--
2.53.0
On 2/27/26 12:11PM, Helen Koike wrote:
> 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>
Applied to jfs-next.
Thanks!
Shaggy
> ---
> fs/jfs/jfs_logmgr.c | 16 +++++++---------
> fs/jfs/jfs_logmgr.h | 7 +++++++
> fs/jfs/jfs_umount.c | 10 ++++++++++
> 3 files changed, 24 insertions(+), 9 deletions(-)
>
> diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c
> index 5b1c5da04163..59f94c28007d 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
> @@ -402,6 +402,13 @@ struct jfs_log {
> int no_integrity; /* 3: flag to disable journaling to disk */
> };
>
> +/*
> + * 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
> */
> 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"
>
> @@ -57,6 +58,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)
> */
> @@ -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
© 2016 - 2026 Red Hat, Inc.