mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-09-18 23:09:29 +02:00
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>
This commit is contained in:
committed by
Dave Kleikamp
parent
b15e431063
commit
ca5848ae87
+7
-9
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user