From: Li Xinhai lixinhai.lxh@gmail.com
mainline inclusion from mainline-v5.12-rc1 commit ee8ab1903e3d912d8f10bedbf96c3b6a1c8cbede category: bugfix bugzilla: 175120 CVE: NA
-------------------------------------------------
In case the vma will continue to be used after unlink its relevant anon_vma, we need to reset the vma->anon_vma pointer to NULL. So, later when fault happen within this vma again, a new anon_vma will be prepared.
By this way, the vma will only be checked for reverse mapping of pages which been fault in after the unlink_anon_vmas call.
Currently, the mremap with MREMAP_DONTUNMAP scenario will continue use the vma after moved its page table entries to a new vma. For other scenarios, the vma itself will be freed after call unlink_anon_vmas.
Link: https://lkml.kernel.org/r/20210119075126.3513154-1-lixinhai.lxh@gmail.com Signed-off-by: Li Xinhai lixinhai.lxh@gmail.com Cc: Andrea Arcangeli aarcange@redhat.com Cc: Brian Geffon bgeffon@google.com Cc: Kirill A. Shutemov kirill.shutemov@linux.intel.com Cc: Lokesh Gidra lokeshgidra@google.com Cc: Minchan Kim minchan@kernel.org Cc: Vlastimil Babka vbabka@suse.cz Signed-off-by: Andrew Morton akpm@linux-foundation.org Signed-off-by: Linus Torvalds torvalds@linux-foundation.org
Signed-off-by: Nanyong Sun sunnanyong@huawei.com Reviewed-by: tong tiangen tongtiangen@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- mm/rmap.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/mm/rmap.c b/mm/rmap.c index 738e07ee35345..7debdf0cc6785 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -406,8 +406,15 @@ void unlink_anon_vmas(struct vm_area_struct *vma) list_del(&avc->same_vma); anon_vma_chain_free(avc); } - if (vma->anon_vma) + if (vma->anon_vma) { vma->anon_vma->degree--; + + /* + * vma would still be needed after unlink, and anon_vma will be prepared + * when handle fault. + */ + vma->anon_vma = NULL; + } unlock_anon_vma_root(root);
/*
From: Chengguang Xu cgxu519@zoho.com.cn
mainline inclusion from mainline-5.3-rc1 commit f4c3fb8c433f1818da46b720754a5d4a8525fdf0 category: bugfix bugzilla: 174001 CVE: NA
-------------------------------------------------
Introduce helper function ext2_xattr_entry_valid() for xattr entry validation and clean up the entry check related code.
Reviewed-by: Andreas Dilger adilger@dilger.ca Signed-off-by: Chengguang Xu cgxu519@zoho.com.cn Signed-off-by: Jan Kara jack@suse.cz
Conflicts: fs/ext2/xattr.c
Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext2/xattr.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-)
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index dd8f10db82e99..417cab0bdc864 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -134,6 +134,22 @@ ext2_xattr_handler(int name_index) return handler; }
+static bool +ext2_xattr_entry_valid(struct ext2_xattr_entry *entry, size_t end_offs) +{ + size_t size; + + if (entry->e_value_block != 0) + return false; + + size = le32_to_cpu(entry->e_value_size); + if (size > end_offs || + le16_to_cpu(entry->e_value_offs) + size > end_offs) + return false; + + return true; +} + /* * ext2_xattr_get() * @@ -203,14 +219,10 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", error = -ENODATA; goto cleanup; found: - /* check the buffer size */ - if (entry->e_value_block != 0) - goto bad_block; - size = le32_to_cpu(entry->e_value_size); - if (size > inode->i_sb->s_blocksize || - le16_to_cpu(entry->e_value_offs) + size > inode->i_sb->s_blocksize) + if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize)) goto bad_block;
+ size = le32_to_cpu(entry->e_value_size); if (ext2_xattr_cache_insert(ea_block_cache, bh)) ea_idebug(inode, "cache insert failed"); if (buffer) { @@ -470,12 +482,10 @@ bad_block: ext2_error(sb, "ext2_xattr_set", if (flags & XATTR_CREATE) goto cleanup; if (!here->e_value_block && here->e_value_size) { - size_t size = le32_to_cpu(here->e_value_size); - - if (le16_to_cpu(here->e_value_offs) + size > - sb->s_blocksize || size > sb->s_blocksize) + if (!ext2_xattr_entry_valid(here, sb->s_blocksize)) goto bad_block; - free += EXT2_XATTR_SIZE(size); + free += EXT2_XATTR_SIZE( + le32_to_cpu(here->e_value_size)); } free += EXT2_XATTR_LEN(name_len); }
From: Jan Kara jack@suse.cz
mainline inclusion from mainline-5.3-rc1 commit 8cd0f2ba787a1a1758dbe063fe6a26ceccd37c24 category: bugfix bugzilla: 174001 CVE: NA
-------------------------------------------------
There are two very similar loops when searching xattr to set. Just merge them.
Reviewed-by: Chengguang Xu cgxu519@zoho.com.cn Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext2/xattr.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-)
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 417cab0bdc864..6d3d7ee6d6f1b 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -425,28 +425,12 @@ bad_block: ext2_error(sb, "ext2_xattr_set", error = -EIO; goto cleanup; } - /* Find the named attribute. */ - here = FIRST_ENTRY(bh); - while (!IS_LAST_ENTRY(here)) { - struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(here); - if ((char *)next >= end) - goto bad_block; - if (!here->e_value_block && here->e_value_size) { - size_t offs = le16_to_cpu(here->e_value_offs); - if (offs < min_offs) - min_offs = offs; - } - not_found = name_index - here->e_name_index; - if (!not_found) - not_found = name_len - here->e_name_len; - if (!not_found) - not_found = memcmp(name, here->e_name,name_len); - if (not_found <= 0) - break; - here = next; - } - last = here; - /* We still need to compute min_offs and last. */ + /* + * Find the named attribute. If not found, 'here' will point + * to entry where the new attribute should be inserted to + * maintain sorting. + */ + last = FIRST_ENTRY(bh); while (!IS_LAST_ENTRY(last)) { struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); if ((char *)next >= end) @@ -456,8 +440,21 @@ bad_block: ext2_error(sb, "ext2_xattr_set", if (offs < min_offs) min_offs = offs; } + if (not_found > 0) { + not_found = name_index - last->e_name_index; + if (!not_found) + not_found = name_len - last->e_name_len; + if (!not_found) { + not_found = memcmp(name, last->e_name, + name_len); + } + if (not_found <= 0) + here = last; + } last = next; } + if (not_found > 0) + here = last;
/* Check whether we have enough space left. */ free = min_offs - ((char*)last - (char*)header) - sizeof(__u32);
From: Jan Kara jack@suse.cz
mainline inclusion from mainline-5.3-rc1 commit 6c71b489ecfd927966571348f4e4135169a9fbd5 category: bugfix bugzilla: 174001 CVE: NA
-------------------------------------------------
Check every entry in xattr block for validity in ext2_xattr_set() to detect on disk corruption early. Also since e_value_block field in xattr entry is never != 0 in a valid filesystem, just remove checks for it once we have established entries are valid.
Reviewed-by: Chengguang Xu cgxu519@zoho.com.cn Signed-off-by: Jan Kara jack@suse.cz Signed-off-by: Baokun Li libaokun1@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext2/xattr.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-)
diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 6d3d7ee6d6f1b..b1c361e24a305 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -208,6 +208,8 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", EXT2_XATTR_NEXT(entry); if ((char *)next >= end) goto bad_block; + if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize)) + goto bad_block; if (name_index == entry->e_name_index && name_len == entry->e_name_len && memcmp(name, entry->e_name, name_len) == 0) @@ -219,9 +221,6 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_get", error = -ENODATA; goto cleanup; found: - if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize)) - goto bad_block; - size = le32_to_cpu(entry->e_value_size); if (ext2_xattr_cache_insert(ea_block_cache, bh)) ea_idebug(inode, "cache insert failed"); @@ -294,6 +293,8 @@ bad_block: ext2_error(inode->i_sb, "ext2_xattr_list",
if ((char *)next >= end) goto bad_block; + if (!ext2_xattr_entry_valid(entry, inode->i_sb->s_blocksize)) + goto bad_block; entry = next; } if (ext2_xattr_cache_insert(ea_block_cache, bh)) @@ -435,7 +436,9 @@ bad_block: ext2_error(sb, "ext2_xattr_set", struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(last); if ((char *)next >= end) goto bad_block; - if (!last->e_value_block && last->e_value_size) { + if (!ext2_xattr_entry_valid(last, sb->s_blocksize)) + goto bad_block; + if (last->e_value_size) { size_t offs = le16_to_cpu(last->e_value_offs); if (offs < min_offs) min_offs = offs; @@ -478,12 +481,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set", error = -EEXIST; if (flags & XATTR_CREATE) goto cleanup; - if (!here->e_value_block && here->e_value_size) { - if (!ext2_xattr_entry_valid(here, sb->s_blocksize)) - goto bad_block; - free += EXT2_XATTR_SIZE( - le32_to_cpu(here->e_value_size)); - } + free += EXT2_XATTR_SIZE(le32_to_cpu(here->e_value_size)); free += EXT2_XATTR_LEN(name_len); } error = -ENOSPC; @@ -548,7 +546,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set", here->e_name_len = name_len; memcpy(here->e_name, name, name_len); } else { - if (!here->e_value_block && here->e_value_size) { + if (here->e_value_size) { char *first_val = (char *)header + min_offs; size_t offs = le16_to_cpu(here->e_value_offs); char *val = (char *)header + offs; @@ -575,7 +573,7 @@ bad_block: ext2_error(sb, "ext2_xattr_set", last = ENTRY(header+1); while (!IS_LAST_ENTRY(last)) { size_t o = le16_to_cpu(last->e_value_offs); - if (!last->e_value_block && o < offs) + if (o < offs) last->e_value_offs = cpu_to_le16(o + size); last = EXT2_XATTR_NEXT(last);
From: yangerkun yangerkun@huawei.com
hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I46HJ6 CVE: NA ---------------------------
This reverts commit 0875a4c4a55932660b602c1c266aed88b6b83231.
After this patch, we will first call ext4_es_unregister_shrinker and destroy some percpu counter which will try to access will latter call trace:
[ 45.808127] Internal error: Oops: 96000004 [#1] SMP [ 45.812986] Modules linked in: realtek hclge hns3 megaraid_sas hisi_sas_v3_hw hibmc_drm hisi_sas_main host_edma_drv hnae3 [ 45.823896] Process mount (pid: 1187, stack limit = 0x00000000e0bd7181) [ 45.830481] CPU: 9 PID: 1187 Comm: mount Not tainted 4.19.90_4.19.90-2108.7.0+ #2 [ 45.837929] Hardware name: Huawei TaiShan 2280 V2/BC82AMDC, BIOS 2280-V2 CS V3.26.01 06/14/2019 [ 45.846587] pstate: 10400009 (nzcV daif +PAN -UAO) [ 45.851359] pc : percpu_counter_add_batch+0x5c/0x358 [ 45.856303] lr : ext4_es_free_extent+0xd4/0x4a8 [ 45.860812] sp : ffff80262a60f170 [ 45.864112] x29: ffff80262a60f170 x28: dfff200000000000 [ 45.869399] x27: ffff8026403e65cc x26: 0000000000000000 [ 45.874686] x25: ffff80266c429e20 x24: 0000000000000100 [ 45.879973] x23: 1ffff004cd8853c4 x22: ffffffffffffffff [ 45.885260] x21: 0000000000000000 x20: 00006026b7a31000 [ 45.890547] x19: ffff80266c429e00 x18: 0000000000000000 [ 45.895833] x17: 0000000000000000 x16: 0000000000000000 [ 45.901120] x15: 1fffe4000504bd02 x14: ffff200023ba1adc [ 45.906406] x13: ffff200024332530 x12: ffff20002433240c [ 45.911693] x11: ffff2000243304f4 x10: ffff200024328f6c [ 45.916980] x9 : 1ffff004c807ccb9 x8 : ffff200023b75950 [ 45.922266] x7 : ffff200023ba1fe0 x6 : 0000000000000004 [ 45.927553] x5 : 0000000000000000 x4 : 0000000000000000 [ 45.932839] x3 : 00000c04d6f46200 x2 : dfff200000000000 [ 45.938126] x1 : 0000000000000003 x0 : 00006026b7a31000 [ 45.943413] Call trace: [ 45.945851] percpu_counter_add_batch+0x5c/0x358 [ 45.950446] ext4_es_free_extent+0xd4/0x4a8 [ 45.954610] __es_remove_extent+0x37c/0x598 [ 45.958773] ext4_es_remove_extent+0x6c/0x270 [ 45.963110] ext4_clear_inode+0x50/0x188 [ 45.967016] ext4_evict_inode+0x314/0x1450 [ 45.971094] evict+0x238/0x5a0 [ 45.974136] iput+0x2bc/0x6b8 [ 45.977090] jbd2_journal_destroy+0x408/0x800 [ 45.981428] ext4_fill_super+0x5a04/0x8cc0 [ 45.985505] mount_bdev+0x268/0x328 [ 45.988978] ext4_mount+0x44/0x58 [ 45.992277] mount_fs+0x68/0x390 [ 45.995492] vfs_kern_mount.part.2+0x54/0x388 [ 45.999830] do_mount+0xa5c/0x20d0 [ 46.003216] ksys_mount+0x9c/0x118 [ 46.006603] __arm64_sys_mount+0xa8/0x108 [ 46.010595] el0_svc_common+0x10c/0x4a0 [ 46.014415] el0_svc_handler+0x170/0x248 [ 46.018320] el0_svc+0x10/0x218 [ 46.021448] Code: f2fbffe2 d343fc03 92400801 11000c21 (38e26862) [ 46.027513] ---[ end trace 316fdb8833588599 ]--- [ 46.037646] Kernel panic - not syncing: Fatal exception [ 46.042848] SMP: stopping secondary CPUs [ 46.046779] Kernel Offset: 0x1baf0000 from 0xffff200008000000 [ 46.052500] CPU features: 0x12,a2a00a38 [ 46.056318] Memory Limit: none [ 46.064887] Rebooting in 1 seconds.. [ 47.068489] SMP: stopping secondary CPUs [ 48.158471] SMP: failed to stop secondary CPUs 0-127
We first revert this patch. And the problem which this patch try to fix will fixed soon.
Signed-off-by: yangerkun yangerkun@huawei.com Reviewed-by: Zhang Yi yi.zhang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- fs/ext4/super.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 0783f85a1c6cc..d793e597c0623 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -4831,15 +4831,14 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) ext4_xattr_destroy_cache(sbi->s_ea_block_cache); sbi->s_ea_block_cache = NULL; } -failed_mount3a: - ext4_es_unregister_shrinker(sbi); -failed_mount3: - flush_work(&sbi->s_error_work); - if (sbi->s_journal) { jbd2_journal_destroy(sbi->s_journal); sbi->s_journal = NULL; } +failed_mount3a: + ext4_es_unregister_shrinker(sbi); +failed_mount3: + flush_work(&sbi->s_error_work); del_timer_sync(&sbi->s_err_report); ext4_stop_mmpd(sbi); failed_mount2: