From 592acbf16821288ecdc4192c47e3774a4c48bb64 Mon Sep 17 00:00:00 2001 From: Sriram Rajagopalan Date: Fri, 10 May 2019 19:28:06 -0400 Subject: ext4: zero out the unused memory region in the extent tree block This commit zeroes out the unused memory region in the buffer_head corresponding to the extent metablock after writing the extent header and the corresponding extent node entries. This is done to prevent random uninitialized data from getting into the filesystem when the extent block is synced. This fixes CVE-2019-11833. Signed-off-by: Sriram Rajagopalan Signed-off-by: Theodore Ts'o Cc: stable@kernel.org --- fs/ext4/extents.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 0f89f5190cd7..f2c62e2a0c98 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -1035,6 +1035,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, __le32 border; ext4_fsblk_t *ablocks = NULL; /* array of allocated blocks */ int err = 0; + size_t ext_size = 0; /* make decision: where to split? */ /* FIXME: now decision is simplest: at current extent */ @@ -1126,6 +1127,10 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, le16_add_cpu(&neh->eh_entries, m); } + /* zero out unused area in the extent block */ + ext_size = sizeof(struct ext4_extent_header) + + sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries); + memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); ext4_extent_block_csum_set(inode, neh); set_buffer_uptodate(bh); unlock_buffer(bh); @@ -1205,6 +1210,11 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, sizeof(struct ext4_extent_idx) * m); le16_add_cpu(&neh->eh_entries, m); } + /* zero out unused area in the extent block */ + ext_size = sizeof(struct ext4_extent_header) + + (sizeof(struct ext4_extent) * le16_to_cpu(neh->eh_entries)); + memset(bh->b_data + ext_size, 0, + inode->i_sb->s_blocksize - ext_size); ext4_extent_block_csum_set(inode, neh); set_buffer_uptodate(bh); unlock_buffer(bh); @@ -1270,6 +1280,7 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, ext4_fsblk_t newblock, goal = 0; struct ext4_super_block *es = EXT4_SB(inode->i_sb)->s_es; int err = 0; + size_t ext_size = 0; /* Try to prepend new index to old one */ if (ext_depth(inode)) @@ -1295,9 +1306,11 @@ static int ext4_ext_grow_indepth(handle_t *handle, struct inode *inode, goto out; } + ext_size = sizeof(EXT4_I(inode)->i_data); /* move top-level index/leaf into new block */ - memmove(bh->b_data, EXT4_I(inode)->i_data, - sizeof(EXT4_I(inode)->i_data)); + memmove(bh->b_data, EXT4_I(inode)->i_data, ext_size); + /* zero out unused area in the extent block */ + memset(bh->b_data + ext_size, 0, inode->i_sb->s_blocksize - ext_size); /* set size of new block */ neh = ext_block_hdr(bh); -- cgit v1.2.3 From 0d52154bb0a700abb459a2cbce0a30fc2549b67e Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Fri, 10 May 2019 21:15:47 -0400 Subject: jbd2: fix potential double free When failing from creating cache jbd2_inode_cache, we will destroy the previously created cache jbd2_handle_cache twice. This patch fixes this by moving each cache initialization/destruction to its own separate, individual function. Signed-off-by: Chengguang Xu Signed-off-by: Theodore Ts'o Cc: stable@kernel.org --- fs/jbd2/journal.c | 49 +++++++++++++++++++++++++++++++------------------ fs/jbd2/revoke.c | 32 ++++++++++++++++++++------------ fs/jbd2/transaction.c | 8 +++++--- include/linux/jbd2.h | 8 +++++--- 4 files changed, 61 insertions(+), 36 deletions(-) diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 37e16d969925..43df0c943229 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -2375,22 +2375,19 @@ static struct kmem_cache *jbd2_journal_head_cache; static atomic_t nr_journal_heads = ATOMIC_INIT(0); #endif -static int jbd2_journal_init_journal_head_cache(void) +static int __init jbd2_journal_init_journal_head_cache(void) { - int retval; - - J_ASSERT(jbd2_journal_head_cache == NULL); + J_ASSERT(!jbd2_journal_head_cache); jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head", sizeof(struct journal_head), 0, /* offset */ SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU, NULL); /* ctor */ - retval = 0; if (!jbd2_journal_head_cache) { - retval = -ENOMEM; printk(KERN_EMERG "JBD2: no memory for journal_head cache\n"); + return -ENOMEM; } - return retval; + return 0; } static void jbd2_journal_destroy_journal_head_cache(void) @@ -2636,28 +2633,38 @@ static void __exit jbd2_remove_jbd_stats_proc_entry(void) struct kmem_cache *jbd2_handle_cache, *jbd2_inode_cache; +static int __init jbd2_journal_init_inode_cache(void) +{ + J_ASSERT(!jbd2_inode_cache); + jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0); + if (!jbd2_inode_cache) { + pr_emerg("JBD2: failed to create inode cache\n"); + return -ENOMEM; + } + return 0; +} + static int __init jbd2_journal_init_handle_cache(void) { + J_ASSERT(!jbd2_handle_cache); jbd2_handle_cache = KMEM_CACHE(jbd2_journal_handle, SLAB_TEMPORARY); - if (jbd2_handle_cache == NULL) { + if (!jbd2_handle_cache) { printk(KERN_EMERG "JBD2: failed to create handle cache\n"); return -ENOMEM; } - jbd2_inode_cache = KMEM_CACHE(jbd2_inode, 0); - if (jbd2_inode_cache == NULL) { - printk(KERN_EMERG "JBD2: failed to create inode cache\n"); - kmem_cache_destroy(jbd2_handle_cache); - return -ENOMEM; - } return 0; } +static void jbd2_journal_destroy_inode_cache(void) +{ + kmem_cache_destroy(jbd2_inode_cache); + jbd2_inode_cache = NULL; +} + static void jbd2_journal_destroy_handle_cache(void) { kmem_cache_destroy(jbd2_handle_cache); jbd2_handle_cache = NULL; - kmem_cache_destroy(jbd2_inode_cache); - jbd2_inode_cache = NULL; } /* @@ -2668,11 +2675,15 @@ static int __init journal_init_caches(void) { int ret; - ret = jbd2_journal_init_revoke_caches(); + ret = jbd2_journal_init_revoke_record_cache(); + if (ret == 0) + ret = jbd2_journal_init_revoke_table_cache(); if (ret == 0) ret = jbd2_journal_init_journal_head_cache(); if (ret == 0) ret = jbd2_journal_init_handle_cache(); + if (ret == 0) + ret = jbd2_journal_init_inode_cache(); if (ret == 0) ret = jbd2_journal_init_transaction_cache(); return ret; @@ -2680,9 +2691,11 @@ static int __init journal_init_caches(void) static void jbd2_journal_destroy_caches(void) { - jbd2_journal_destroy_revoke_caches(); + jbd2_journal_destroy_revoke_record_cache(); + jbd2_journal_destroy_revoke_table_cache(); jbd2_journal_destroy_journal_head_cache(); jbd2_journal_destroy_handle_cache(); + jbd2_journal_destroy_inode_cache(); jbd2_journal_destroy_transaction_cache(); jbd2_journal_destroy_slabs(); } diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index a1143e57a718..69b9bc329964 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c @@ -178,33 +178,41 @@ static struct jbd2_revoke_record_s *find_revoke_record(journal_t *journal, return NULL; } -void jbd2_journal_destroy_revoke_caches(void) +void jbd2_journal_destroy_revoke_record_cache(void) { kmem_cache_destroy(jbd2_revoke_record_cache); jbd2_revoke_record_cache = NULL; +} + +void jbd2_journal_destroy_revoke_table_cache(void) +{ kmem_cache_destroy(jbd2_revoke_table_cache); jbd2_revoke_table_cache = NULL; } -int __init jbd2_journal_init_revoke_caches(void) +int __init jbd2_journal_init_revoke_record_cache(void) { J_ASSERT(!jbd2_revoke_record_cache); - J_ASSERT(!jbd2_revoke_table_cache); - jbd2_revoke_record_cache = KMEM_CACHE(jbd2_revoke_record_s, SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY); - if (!jbd2_revoke_record_cache) - goto record_cache_failure; + if (!jbd2_revoke_record_cache) { + pr_emerg("JBD2: failed to create revoke_record cache\n"); + return -ENOMEM; + } + return 0; +} + +int __init jbd2_journal_init_revoke_table_cache(void) +{ + J_ASSERT(!jbd2_revoke_table_cache); jbd2_revoke_table_cache = KMEM_CACHE(jbd2_revoke_table_s, SLAB_TEMPORARY); - if (!jbd2_revoke_table_cache) - goto table_cache_failure; - return 0; -table_cache_failure: - jbd2_journal_destroy_revoke_caches(); -record_cache_failure: + if (!jbd2_revoke_table_cache) { + pr_emerg("JBD2: failed to create revoke_table cache\n"); return -ENOMEM; + } + return 0; } static struct jbd2_revoke_table_s *jbd2_journal_init_revoke_table(int hash_size) diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index f940d31c2adc..8ca4fddc705f 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -42,9 +42,11 @@ int __init jbd2_journal_init_transaction_cache(void) 0, SLAB_HWCACHE_ALIGN|SLAB_TEMPORARY, NULL); - if (transaction_cache) - return 0; - return -ENOMEM; + if (!transaction_cache) { + pr_emerg("JBD2: failed to create transaction cache\n"); + return -ENOMEM; + } + return 0; } void jbd2_journal_destroy_transaction_cache(void) diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 0f919d5fe84f..2cf6e04b08fc 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1318,7 +1318,7 @@ extern void __wait_on_journal (journal_t *); /* Transaction cache support */ extern void jbd2_journal_destroy_transaction_cache(void); -extern int jbd2_journal_init_transaction_cache(void); +extern int __init jbd2_journal_init_transaction_cache(void); extern void jbd2_journal_free_transaction(transaction_t *); /* @@ -1446,8 +1446,10 @@ static inline void jbd2_free_inode(struct jbd2_inode *jinode) /* Primary revoke support */ #define JOURNAL_REVOKE_DEFAULT_HASH 256 extern int jbd2_journal_init_revoke(journal_t *, int); -extern void jbd2_journal_destroy_revoke_caches(void); -extern int jbd2_journal_init_revoke_caches(void); +extern void jbd2_journal_destroy_revoke_record_cache(void); +extern void jbd2_journal_destroy_revoke_table_cache(void); +extern int __init jbd2_journal_init_revoke_record_cache(void); +extern int __init jbd2_journal_init_revoke_table_cache(void); extern void jbd2_journal_destroy_revoke(journal_t *); extern int jbd2_journal_revoke (handle_t *, unsigned long long, struct buffer_head *); -- cgit v1.2.3 From 57a0da28ced8707cb9f79f071a016b9d005caf5a Mon Sep 17 00:00:00 2001 From: Lukas Czerner Date: Fri, 10 May 2019 21:45:33 -0400 Subject: ext4: fix data corruption caused by overlapping unaligned and aligned IO Unaligned AIO must be serialized because the zeroing of partial blocks of unaligned AIO can result in data corruption in case it's overlapping another in flight IO. Currently we wait for all unwritten extents before we submit unaligned AIO which protects data in case of unaligned AIO is following overlapping IO. However if a unaligned AIO is followed by overlapping aligned AIO we can still end up corrupting data. To fix this, we must make sure that the unaligned AIO is the only IO in flight by waiting for unwritten extents conversion not just before the IO submission, but right after it as well. This problem can be reproduced by xfstest generic/538 Signed-off-by: Lukas Czerner Signed-off-by: Theodore Ts'o Cc: stable@kernel.org --- fs/ext4/file.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/fs/ext4/file.c b/fs/ext4/file.c index 98ec11f69cd4..2c5baa5e8291 100644 --- a/fs/ext4/file.c +++ b/fs/ext4/file.c @@ -264,6 +264,13 @@ ext4_file_write_iter(struct kiocb *iocb, struct iov_iter *from) } ret = __generic_file_write_iter(iocb, from); + /* + * Unaligned direct AIO must be the only IO in flight. Otherwise + * overlapping aligned IO after unaligned might result in data + * corruption. + */ + if (ret == -EIOCBQUEUED && unaligned_aio) + ext4_unwritten_wait(inode); inode_unlock(inode); if (ret > 0) -- cgit v1.2.3 From 08fc98a4d6424af66eb3ac4e2cedd2fc927ed436 Mon Sep 17 00:00:00 2001 From: Sahitya Tummala Date: Fri, 10 May 2019 22:00:33 -0400 Subject: ext4: fix use-after-free in dx_release() The buffer_head (frames[0].bh) and it's corresping page can be potentially free'd once brelse() is done inside the for loop but before the for loop exits in dx_release(). It can be free'd in another context, when the page cache is flushed via drop_caches_sysctl_handler(). This results into below data abort when accessing info->indirect_levels in dx_release(). Unable to handle kernel paging request at virtual address ffffffc17ac3e01e Call trace: dx_release+0x70/0x90 ext4_htree_fill_tree+0x2d4/0x300 ext4_readdir+0x244/0x6f8 iterate_dir+0xbc/0x160 SyS_getdents64+0x94/0x174 Signed-off-by: Sahitya Tummala Signed-off-by: Theodore Ts'o Reviewed-by: Andreas Dilger Cc: stable@kernel.org --- fs/ext4/namei.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index e917830eae84..ac7457fef9e6 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -872,12 +872,15 @@ static void dx_release(struct dx_frame *frames) { struct dx_root_info *info; int i; + unsigned int indirect_levels; if (frames[0].bh == NULL) return; info = &((struct dx_root *)frames[0].bh->b_data)->info; - for (i = 0; i <= info->indirect_levels; i++) { + /* save local copy, "info" may be freed after brelse() */ + indirect_levels = info->indirect_levels; + for (i = 0; i <= indirect_levels; i++) { if (frames[i].bh == NULL) break; brelse(frames[i].bh); -- cgit v1.2.3 From fbbbbd2f28aec991f3fbc248df211550fbdfd58c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 10 May 2019 22:06:38 -0400 Subject: ext4: unsigned int compared against zero There are two cases where u32 variables n and err are being checked for less than zero error values, the checks is always false because the variables are not signed. Fix this by making the variables ints. Addresses-Coverity: ("Unsigned compared against 0") Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity") Signed-off-by: Colin Ian King Signed-off-by: Theodore Ts'o --- fs/ext4/block_validity.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 968f163b5feb..8d03550aaae3 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -142,7 +142,8 @@ static int ext4_protect_reserved_inode(struct super_block *sb, u32 ino) struct inode *inode; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_map_blocks map; - u32 i = 0, err = 0, num, n; + u32 i = 0, num; + int err = 0, n; if ((ino < EXT4_ROOT_INO) || (ino > le32_to_cpu(sbi->s_es->s_inodes_count))) -- cgit v1.2.3 From 0ba33facfc9bb556d1938caa67dfe452695a9be9 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 12 May 2019 04:49:47 -0400 Subject: ext4: fix miscellaneous sparse warnings Signed-off-by: Theodore Ts'o --- fs/ext4/fsmap.c | 2 +- fs/ext4/ioctl.c | 2 +- fs/ext4/super.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/ext4/fsmap.c b/fs/ext4/fsmap.c index 4b99e2db95b8..dbccf46f1770 100644 --- a/fs/ext4/fsmap.c +++ b/fs/ext4/fsmap.c @@ -626,7 +626,7 @@ int ext4_getfsmap(struct super_block *sb, struct ext4_fsmap_head *head, { struct ext4_fsmap dkeys[2]; /* per-dev keys */ struct ext4_getfsmap_dev handlers[EXT4_GETFSMAP_DEVS]; - struct ext4_getfsmap_info info = {0}; + struct ext4_getfsmap_info info = { NULL }; int i; int error = 0; diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index 7e85ecf0b849..e486e49b31ed 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c @@ -608,7 +608,7 @@ static int ext4_getfsmap_format(struct ext4_fsmap *xfm, void *priv) static int ext4_ioc_getfsmap(struct super_block *sb, struct fsmap_head __user *arg) { - struct getfsmap_info info = {0}; + struct getfsmap_info info = { NULL }; struct ext4_fsmap_head xhead = {0}; struct fsmap_head head; bool aborted = false; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index fc6fa2c93e77..5013d04b41fd 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4679,7 +4679,7 @@ failed_mount: #ifdef CONFIG_QUOTA for (i = 0; i < EXT4_MAXQUOTAS; i++) - kfree(sbi->s_qf_names[i]); + kfree(get_qf_name(sb, sbi, i)); #endif ext4_blkdev_remove(sbi); brelse(bh); -- cgit v1.2.3 From 15f0d8d0bafb0d841dde53af549c4c44b059d7f5 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 12 May 2019 04:56:51 -0400 Subject: unicode: add missing check for an error return from utf8lookup() Signed-off-by: Theodore Ts'o Cc: Gabriel Krisman Bertazi --- fs/unicode/utf8-norm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/unicode/utf8-norm.c b/fs/unicode/utf8-norm.c index 20d440c3f2db..801ed6d2ea37 100644 --- a/fs/unicode/utf8-norm.c +++ b/fs/unicode/utf8-norm.c @@ -714,6 +714,8 @@ int utf8byte(struct utf8cursor *u8c) } leaf = utf8lookup(u8c->data, u8c->hangul, u8c->s); + if (!leaf) + return -1; ccc = LEAF_CCC(leaf); } -- cgit v1.2.3 From 7fb64133360b10edcae3c6f5afffaa449668831e Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 12 May 2019 13:26:08 -0400 Subject: unicode: update to Unicode 12.1.0 final Signed-off-by: Theodore Ts'o Cc: Gabriel Krisman Bertazi --- fs/unicode/README.utf8data | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/fs/unicode/README.utf8data b/fs/unicode/README.utf8data index 9307cf0727de..c73786807d3b 100644 --- a/fs/unicode/README.utf8data +++ b/fs/unicode/README.utf8data @@ -5,29 +5,15 @@ The full set of files can be found here: http://www.unicode.org/Public/12.1.0/ucd/ -Note! - -The URL's listed below are not stable. That's because Unicode 12.1.0 -has not been officially released yet; it is scheduled to be released -on May 8, 2019. We taking Unicode 12.1.0 a few weeks early because it -contains a new Japanese character which is required in order to -specify Japenese dates after May 1, 2019, when Crown Prince Naruhito -ascends to the Chrysanthemum Throne. (Isn't internationalization fun? -The abdication of Emperor Akihito of Japan is requiring dozens of -software packages to be updated with only a month's notice. :-) - -We will update the URL's (and any needed changes to the checksums) -after the final Unicode 12.1.0 is released. - Individual source links: - https://www.unicode.org/Public/12.1.0/ucd/CaseFolding-12.1.0d2.txt - https://www.unicode.org/Public/12.1.0/ucd/DerivedAge-12.1.0d3.txt - https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass-12.1.0d2.txt - https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties-12.1.0d2.txt - https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections-12.1.0d1.txt - https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest-12.1.0d3.txt - https://www.unicode.org/Public/12.1.0/ucd/UnicodeData-12.1.0d2.txt + https://www.unicode.org/Public/12.1.0/ucd/CaseFolding.txt + https://www.unicode.org/Public/12.1.0/ucd/DerivedAge.txt + https://www.unicode.org/Public/12.1.0/ucd/extracted/DerivedCombiningClass.txt + https://www.unicode.org/Public/12.1.0/ucd/DerivedCoreProperties.txt + https://www.unicode.org/Public/12.1.0/ucd/NormalizationCorrections.txt + https://www.unicode.org/Public/12.1.0/ucd/NormalizationTest.txt + https://www.unicode.org/Public/12.1.0/ucd/UnicodeData.txt md5sums (verify by running "md5sum -c README.utf8data"): -- cgit v1.2.3 From 170417c8c7bb2cbbdd949bf5c443c0c8f24a203b Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 15 May 2019 00:51:19 -0400 Subject: ext4: fix block validity checks for journal inodes using indirect blocks Commit 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity") failed to add an exception for the journal inode in ext4_check_blockref(), which is the function used by ext4_get_branch() for indirect blocks. This caused attempts to read from the ext3-style journals to fail with: [ 848.968550] EXT4-fs error (device sdb7): ext4_get_branch:171: inode #8: block 30343695: comm jbd2/sdb7-8: invalid block Fix this by adding the missing exception check. Fixes: 345c0dbf3a30 ("ext4: protect journal inode's blocks using block_validity") Reported-by: Arthur Marsh Signed-off-by: Theodore Ts'o --- fs/ext4/block_validity.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/ext4/block_validity.c b/fs/ext4/block_validity.c index 8d03550aaae3..8e83741b02e0 100644 --- a/fs/ext4/block_validity.c +++ b/fs/ext4/block_validity.c @@ -277,6 +277,11 @@ int ext4_check_blockref(const char *function, unsigned int line, __le32 *bref = p; unsigned int blk; + if (ext4_has_feature_journal(inode->i_sb) && + (inode->i_ino == + le32_to_cpu(EXT4_SB(inode->i_sb)->s_es->s_journal_inum))) + return 0; + while (bref < p+max) { blk = le32_to_cpu(*bref++); if (blk && -- cgit v1.2.3 From 2c1d0e3631e5732dba98ef49ac0bec1388776793 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Fri, 17 May 2019 17:37:18 -0400 Subject: ext4: avoid panic during forced reboot due to aborted journal Handling of aborted journal is a special code path different from standard ext4_error() one and it can call panic() as well. Commit 1dc1097ff60e ("ext4: avoid panic during forced reboot") forgot to update this path so fix that omission. Fixes: 1dc1097ff60e ("ext4: avoid panic during forced reboot") Signed-off-by: Jan Kara Signed-off-by: Theodore Ts'o Cc: stable@kernel.org # 5.1 --- fs/ext4/super.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 5013d04b41fd..272e1881b5f8 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -699,7 +699,7 @@ void __ext4_abort(struct super_block *sb, const char *function, jbd2_journal_abort(EXT4_SB(sb)->s_journal, -EIO); save_error_info(sb, function, line); } - if (test_opt(sb, ERRORS_PANIC)) { + if (test_opt(sb, ERRORS_PANIC) && !system_going_down()) { if (EXT4_SB(sb)->s_journal && !(EXT4_SB(sb)->s_journal->j_flags & JBD2_REC_ERR)) return; -- cgit v1.2.3