All of lore.kernel.org
 help / color / mirror / Atom feed
From: Baokun Li <libaokun@huaweicloud.com>
To: gregkh@linuxfoundation.org
Cc: sashal@kernel.org, yangerkun@huawei.com, Jan Kara <jack@suse.cz>,
	Ojaswin Mujoo <ojaswin@linux.ibm.com>,
	Theodore Ts'o <tytso@mit.edu>,
	libaokun@huaweicloud.com, stable@vger.kernel.org
Subject: Re: [PATCH 6.6/6.9 v2 2/2] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists()
Date: Tue, 16 Jul 2024 10:11:55 +0800	[thread overview]
Message-ID: <c8784653-bd67-4839-b2a4-bbbfbfa3ba14@huaweicloud.com> (raw)
In-Reply-To: <20240619121952.3508695-2-libaokun@huaweicloud.com>

On 2024/6/19 20:19, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
>
> [ Upstream commit 13df4d44a3aaabe61cd01d277b6ee23ead2a5206 ]
>
> We can trigger a slab-out-of-bounds with the following commands:
>
>      mkfs.ext4 -F /dev/$disk 10G
>      mount /dev/$disk /tmp/test
>      echo 2147483647 > /sys/fs/ext4/$disk/mb_group_prealloc
>      echo test > /tmp/test/file && sync
>
> ==================================================================
> BUG: KASAN: slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists+0x8a/0x200 [ext4]
> Read of size 8 at addr ffff888121b9d0f0 by task kworker/u2:0/11
> CPU: 0 PID: 11 Comm: kworker/u2:0 Tainted: GL 6.7.0-next-20240118 #521
> Call Trace:
>   dump_stack_lvl+0x2c/0x50
>   kasan_report+0xb6/0xf0
>   ext4_mb_find_good_group_avg_frag_lists+0x8a/0x200 [ext4]
>   ext4_mb_regular_allocator+0x19e9/0x2370 [ext4]
>   ext4_mb_new_blocks+0x88a/0x1370 [ext4]
>   ext4_ext_map_blocks+0x14f7/0x2390 [ext4]
>   ext4_map_blocks+0x569/0xea0 [ext4]
>   ext4_do_writepages+0x10f6/0x1bc0 [ext4]
> [...]
> ==================================================================
>
> The flow of issue triggering is as follows:
>
> // Set s_mb_group_prealloc to 2147483647 via sysfs
> ext4_mb_new_blocks
>    ext4_mb_normalize_request
>      ext4_mb_normalize_group_request
>        ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc
>    ext4_mb_regular_allocator
>      ext4_mb_choose_next_group
>        ext4_mb_choose_next_group_best_avail
>          mb_avg_fragment_size_order
>            order = fls(len) - 2 = 29
>          ext4_mb_find_good_group_avg_frag_lists
>            frag_list = &sbi->s_mb_avg_fragment_size[order]
>            if (list_empty(frag_list)) // Trigger SOOB!
>
> At 4k block size, the length of the s_mb_avg_fragment_size list is 14,
> but an oversized s_mb_group_prealloc is set, causing slab-out-of-bounds
> to be triggered by an attempt to access an element at index 29.
>
> Add a new attr_id attr_clusters_in_group with values in the range
> [0, sbi->s_clusters_per_group] and declare mb_group_prealloc as
> that type to fix the issue. In addition avoid returning an order
> from mb_avg_fragment_size_order() greater than MB_NUM_ORDERS(sb)
> and reduce some useless loops.
>
> Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)")
> CC: stable@vger.kernel.org
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Reviewed-by: Jan Kara <jack@suse.cz>
> Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
> Link: https://lore.kernel.org/r/20240319113325.3110393-5-libaokun1@huawei.com
> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> ---
>   fs/ext4/mballoc.c |  4 ++++
>   fs/ext4/sysfs.c   | 15 ++++++++++++++-
>   2 files changed, 18 insertions(+), 1 deletion(-)
>
> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
> index 714f83632e3f..66b5a68b0254 100644
> --- a/fs/ext4/mballoc.c
> +++ b/fs/ext4/mballoc.c
> @@ -831,6 +831,8 @@ static int mb_avg_fragment_size_order(struct super_block *sb, ext4_grpblk_t len)
>   		return 0;
>   	if (order == MB_NUM_ORDERS(sb))
>   		order--;
> +	if (WARN_ON_ONCE(order > MB_NUM_ORDERS(sb)))
> +		order = MB_NUM_ORDERS(sb) - 1;
>   	return order;
>   }
>   
> @@ -1008,6 +1010,8 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
>   	 * goal length.
>   	 */
>   	order = fls(ac->ac_g_ex.fe_len) - 1;
> +	if (WARN_ON_ONCE(order - 1 > MB_NUM_ORDERS(ac->ac_sb)))
> +		order = MB_NUM_ORDERS(ac->ac_sb);
>   	min_order = order - sbi->s_mb_best_avail_max_trim_order;
>   	if (min_order < 0)
>   		min_order = 0;
> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c
> index ca820620b974..d65dccb44ed5 100644
> --- a/fs/ext4/sysfs.c
> +++ b/fs/ext4/sysfs.c
> @@ -29,6 +29,7 @@ typedef enum {
>   	attr_trigger_test_error,
>   	attr_first_error_time,
>   	attr_last_error_time,
> +	attr_clusters_in_group,
>   	attr_feature,
>   	attr_pointer_ui,
>   	attr_pointer_ul,
> @@ -207,13 +208,14 @@ EXT4_ATTR_FUNC(sra_exceeded_retry_limit, 0444);
>   
>   EXT4_ATTR_OFFSET(inode_readahead_blks, 0644, inode_readahead,
>   		 ext4_sb_info, s_inode_readahead_blks);
> +EXT4_ATTR_OFFSET(mb_group_prealloc, 0644, clusters_in_group,
> +		 ext4_sb_info, s_mb_group_prealloc);
>   EXT4_RW_ATTR_SBI_UI(inode_goal, s_inode_goal);
>   EXT4_RW_ATTR_SBI_UI(mb_stats, s_mb_stats);
>   EXT4_RW_ATTR_SBI_UI(mb_max_to_scan, s_mb_max_to_scan);
>   EXT4_RW_ATTR_SBI_UI(mb_min_to_scan, s_mb_min_to_scan);
>   EXT4_RW_ATTR_SBI_UI(mb_order2_req, s_mb_order2_reqs);
>   EXT4_RW_ATTR_SBI_UI(mb_stream_req, s_mb_stream_request);
> -EXT4_RW_ATTR_SBI_UI(mb_group_prealloc, s_mb_group_prealloc);
>   EXT4_RW_ATTR_SBI_UI(mb_max_linear_groups, s_mb_max_linear_groups);
>   EXT4_RW_ATTR_SBI_UI(extent_max_zeroout_kb, s_extent_max_zeroout_kb);
>   EXT4_ATTR(trigger_fs_error, 0200, trigger_test_error);
> @@ -392,6 +394,7 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
>   				(unsigned long long)
>   			percpu_counter_sum(&sbi->s_sra_exceeded_retry_limit));
>   	case attr_inode_readahead:
> +	case attr_clusters_in_group:
>   	case attr_pointer_ui:
>   		if (!ptr)
>   			return 0;
> @@ -469,6 +472,16 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
>   		else
>   			*((unsigned int *) ptr) = t;
>   		return len;
> +	case attr_clusters_in_group:

Hi Greg,

> +		if (!ptr)
> +			return 0;

I've found that the commit that eventually gets merged in doesn't have 
this judgment.

6.6: 677ff4589f15 ("ext4: fix slab-out-of-bounds in 
ext4_mb_find_good_group_avg_frag_lists()")
6.9: b829687ae122 ("ext4: fix slab-out-of-bounds in 
ext4_mb_find_good_group_avg_frag_lists()")

This may result in a null pointer dereference.


History:
https://lore.kernel.org/all/0d620010-c6b4-4f80-a835-451813f957e3@huawei.com/
https://lore.kernel.org/all/20240619121952.3508695-2-libaokun@huaweicloud.com/
https://lore.kernel.org/all/20240625085542.189183696@linuxfoundation.org/

Regards,
Baokun
> +		ret = kstrtouint(skip_spaces(buf), 0, &t);
> +		if (ret)
> +			return ret;
> +		if (t > sbi->s_clusters_per_group)
> +			return -EINVAL;
> +		*((unsigned int *) ptr) = t;
> +		return len;
>   	case attr_pointer_ul:
>   		if (!ptr)
>   			return 0;


  reply	other threads:[~2024-07-16  2:12 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-19 12:19 [PATCH 6.6/6.9 v2 1/2] ext4: avoid overflow when setting values via sysfs libaokun
2024-06-19 12:19 ` [PATCH 6.6/6.9 v2 2/2] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() libaokun
2024-07-16  2:11   ` Baokun Li [this message]
2024-07-16  7:49     ` Greg KH
2024-07-16  8:19       ` Baokun Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=c8784653-bd67-4839-b2a4-bbbfbfa3ba14@huaweicloud.com \
    --to=libaokun@huaweicloud.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jack@suse.cz \
    --cc=ojaswin@linux.ibm.com \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=tytso@mit.edu \
    --cc=yangerkun@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.