* [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow [not found] <20240126085716.1363019-1-libaokun1@huawei.com> @ 2024-01-26 8:57 ` Baokun Li 2024-01-27 2:07 ` Zhang Yi 2024-02-13 16:58 ` Jan Kara 2024-01-26 8:57 ` [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() Baokun Li 1 sibling, 2 replies; 11+ messages in thread From: Baokun Li @ 2024-01-26 8:57 UTC (permalink / raw) To: linux-ext4 Cc: tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, libaokun1, stable We can easily trigger a BUG_ON by using the following commands: mount /dev/$disk /tmp/test echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc echo test > /tmp/test/file && sync ================================================================== kernel BUG at fs/ext4/mballoc.c:2029! invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 RIP: 0010:mb_mark_used+0x358/0x370 [...] Call Trace: ext4_mb_use_best_found+0x56/0x140 ext4_mb_complex_scan_group+0x196/0x2f0 ext4_mb_regular_allocator+0xa92/0xf00 ext4_mb_new_blocks+0x302/0xbc0 ext4_ext_map_blocks+0x95a/0xef0 ext4_map_blocks+0x2b1/0x680 ext4_do_writepages+0x733/0xbd0 [...] ================================================================== In ext4_mb_normalize_group_request(): ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a value range of 0-INT_MAX to avoid the above problem. In addition to the mb_group_prealloc sysfs interface, the following interfaces also have uint to int conversions that result in overflows, and are also fixed. err_ratelimit_burst msg_ratelimit_burst warning_ratelimit_burst err_ratelimit_interval_ms msg_ratelimit_interval_ms warning_ratelimit_interval_ms mb_best_avail_max_trim_order CC: stable@vger.kernel.org Signed-off-by: Baokun Li <libaokun1@huawei.com> --- fs/ext4/sysfs.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c index a5d657fa05cb..6f9f96e00f2f 100644 --- a/fs/ext4/sysfs.c +++ b/fs/ext4/sysfs.c @@ -30,6 +30,7 @@ typedef enum { attr_first_error_time, attr_last_error_time, attr_feature, + attr_pointer_pi, attr_pointer_ui, attr_pointer_ul, attr_pointer_u64, @@ -178,6 +179,9 @@ static struct ext4_attr ext4_attr_##_name = { \ #define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size) \ EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname) +#define EXT4_RW_ATTR_SBI_PI(_name,_elname) \ + EXT4_ATTR_OFFSET(_name, 0644, pointer_pi, ext4_sb_info, _elname) + #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \ EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname) @@ -213,17 +217,17 @@ 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_PI(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); -EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); -EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); -EXT4_RW_ATTR_SBI_UI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); +EXT4_RW_ATTR_SBI_PI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_PI(err_ratelimit_burst, s_err_ratelimit_state.burst); +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); +EXT4_RW_ATTR_SBI_PI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); #ifdef CONFIG_EXT4_DEBUG EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail); #endif @@ -376,6 +380,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, switch (a->attr_id) { case attr_inode_readahead: + case attr_pointer_pi: case attr_pointer_ui: if (a->attr_ptr == ptr_ext4_super_block_offset) return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); @@ -448,6 +453,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, return ret; switch (a->attr_id) { + case attr_pointer_pi: + if ((int)t < 0) + return -EINVAL; + fallthrough; case attr_pointer_ui: if (t != (unsigned int)t) return -EINVAL; -- 2.31.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow 2024-01-26 8:57 ` [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow Baokun Li @ 2024-01-27 2:07 ` Zhang Yi 2024-02-13 16:58 ` Jan Kara 1 sibling, 0 replies; 11+ messages in thread From: Zhang Yi @ 2024-01-27 2:07 UTC (permalink / raw) To: Baokun Li, linux-ext4 Cc: tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yangerkun, chengzhihao1, yukuai3, stable On 2024/1/26 16:57, Baokun Li wrote: > We can easily trigger a BUG_ON by using the following commands: > > mount /dev/$disk /tmp/test > echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc > echo test > /tmp/test/file && sync > > ================================================================== > kernel BUG at fs/ext4/mballoc.c:2029! > invalid opcode: 0000 [#1] PREEMPT SMP PTI > CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 > RIP: 0010:mb_mark_used+0x358/0x370 > [...] > Call Trace: > ext4_mb_use_best_found+0x56/0x140 > ext4_mb_complex_scan_group+0x196/0x2f0 > ext4_mb_regular_allocator+0xa92/0xf00 > ext4_mb_new_blocks+0x302/0xbc0 > ext4_ext_map_blocks+0x95a/0xef0 > ext4_map_blocks+0x2b1/0x680 > ext4_do_writepages+0x733/0xbd0 > [...] > ================================================================== > > In ext4_mb_normalize_group_request(): > ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; > > Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned > int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a > negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). > > Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a > value range of 0-INT_MAX to avoid the above problem. In addition to the > mb_group_prealloc sysfs interface, the following interfaces also have uint > to int conversions that result in overflows, and are also fixed. > > err_ratelimit_burst > msg_ratelimit_burst > warning_ratelimit_burst > err_ratelimit_interval_ms > msg_ratelimit_interval_ms > warning_ratelimit_interval_ms > mb_best_avail_max_trim_order > > CC: stable@vger.kernel.org > Signed-off-by: Baokun Li <libaokun1@huawei.com> Looks good to me. Reviewed-by: Zhang Yi <yi.zhang@huawei.com> > --- > fs/ext4/sysfs.c | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c > index a5d657fa05cb..6f9f96e00f2f 100644 > --- a/fs/ext4/sysfs.c > +++ b/fs/ext4/sysfs.c > @@ -30,6 +30,7 @@ typedef enum { > attr_first_error_time, > attr_last_error_time, > attr_feature, > + attr_pointer_pi, > attr_pointer_ui, > attr_pointer_ul, > attr_pointer_u64, > @@ -178,6 +179,9 @@ static struct ext4_attr ext4_attr_##_name = { \ > #define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size) \ > EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname) > > +#define EXT4_RW_ATTR_SBI_PI(_name,_elname) \ > + EXT4_ATTR_OFFSET(_name, 0644, pointer_pi, ext4_sb_info, _elname) > + > #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \ > EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname) > > @@ -213,17 +217,17 @@ 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_PI(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); > -EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); > +EXT4_RW_ATTR_SBI_PI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(err_ratelimit_burst, s_err_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); > #ifdef CONFIG_EXT4_DEBUG > EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail); > #endif > @@ -376,6 +380,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, > > switch (a->attr_id) { > case attr_inode_readahead: > + case attr_pointer_pi: > case attr_pointer_ui: > if (a->attr_ptr == ptr_ext4_super_block_offset) > return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); > @@ -448,6 +453,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, > return ret; > > switch (a->attr_id) { > + case attr_pointer_pi: > + if ((int)t < 0) > + return -EINVAL; > + fallthrough; > case attr_pointer_ui: > if (t != (unsigned int)t) > return -EINVAL; > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow 2024-01-26 8:57 ` [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow Baokun Li 2024-01-27 2:07 ` Zhang Yi @ 2024-02-13 16:58 ` Jan Kara 2024-02-17 7:41 ` Baokun Li 1 sibling, 1 reply; 11+ messages in thread From: Jan Kara @ 2024-02-13 16:58 UTC (permalink / raw) To: Baokun Li Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable On Fri 26-01-24 16:57:13, Baokun Li wrote: > We can easily trigger a BUG_ON by using the following commands: > > mount /dev/$disk /tmp/test > echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc > echo test > /tmp/test/file && sync > > ================================================================== > kernel BUG at fs/ext4/mballoc.c:2029! > invalid opcode: 0000 [#1] PREEMPT SMP PTI > CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 > RIP: 0010:mb_mark_used+0x358/0x370 > [...] > Call Trace: > ext4_mb_use_best_found+0x56/0x140 > ext4_mb_complex_scan_group+0x196/0x2f0 > ext4_mb_regular_allocator+0xa92/0xf00 > ext4_mb_new_blocks+0x302/0xbc0 > ext4_ext_map_blocks+0x95a/0xef0 > ext4_map_blocks+0x2b1/0x680 > ext4_do_writepages+0x733/0xbd0 > [...] > ================================================================== > > In ext4_mb_normalize_group_request(): > ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; > > Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned > int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a > negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). > > Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a > value range of 0-INT_MAX to avoid the above problem. In addition to the > mb_group_prealloc sysfs interface, the following interfaces also have uint > to int conversions that result in overflows, and are also fixed. > > err_ratelimit_burst > msg_ratelimit_burst > warning_ratelimit_burst > err_ratelimit_interval_ms > msg_ratelimit_interval_ms > warning_ratelimit_interval_ms > mb_best_avail_max_trim_order > > CC: stable@vger.kernel.org > Signed-off-by: Baokun Li <libaokun1@huawei.com> I don't think you need to change s_mb_group_prealloc here and then restrict it even further in the next patch. I'd just leave it alone here. Also I think that limiting mb_best_avail_max_trim_order to 64 instead of INT_MAX will make us more resilient to surprises in the future :) But I don't really insist. Honza > --- > fs/ext4/sysfs.c | 25 +++++++++++++++++-------- > 1 file changed, 17 insertions(+), 8 deletions(-) > > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c > index a5d657fa05cb..6f9f96e00f2f 100644 > --- a/fs/ext4/sysfs.c > +++ b/fs/ext4/sysfs.c > @@ -30,6 +30,7 @@ typedef enum { > attr_first_error_time, > attr_last_error_time, > attr_feature, > + attr_pointer_pi, > attr_pointer_ui, > attr_pointer_ul, > attr_pointer_u64, > @@ -178,6 +179,9 @@ static struct ext4_attr ext4_attr_##_name = { \ > #define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size) \ > EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname) > > +#define EXT4_RW_ATTR_SBI_PI(_name,_elname) \ > + EXT4_ATTR_OFFSET(_name, 0644, pointer_pi, ext4_sb_info, _elname) > + > #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \ > EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname) > > @@ -213,17 +217,17 @@ 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_PI(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); > -EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); > -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); > -EXT4_RW_ATTR_SBI_UI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); > +EXT4_RW_ATTR_SBI_PI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(err_ratelimit_burst, s_err_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); > +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); > +EXT4_RW_ATTR_SBI_PI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); > #ifdef CONFIG_EXT4_DEBUG > EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail); > #endif > @@ -376,6 +380,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, > > switch (a->attr_id) { > case attr_inode_readahead: > + case attr_pointer_pi: > case attr_pointer_ui: > if (a->attr_ptr == ptr_ext4_super_block_offset) > return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); > @@ -448,6 +453,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, > return ret; > > switch (a->attr_id) { > + case attr_pointer_pi: > + if ((int)t < 0) > + return -EINVAL; > + fallthrough; > case attr_pointer_ui: > if (t != (unsigned int)t) > return -EINVAL; > -- > 2.31.1 > -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow 2024-02-13 16:58 ` Jan Kara @ 2024-02-17 7:41 ` Baokun Li 2024-02-23 12:05 ` Jan Kara 0 siblings, 1 reply; 11+ messages in thread From: Baokun Li @ 2024-02-17 7:41 UTC (permalink / raw) To: Jan Kara Cc: linux-ext4, tytso, adilger.kernel, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable, Baokun Li On 2024/2/14 0:58, Jan Kara wrote: > On Fri 26-01-24 16:57:13, Baokun Li wrote: >> We can easily trigger a BUG_ON by using the following commands: >> >> mount /dev/$disk /tmp/test >> echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc >> echo test > /tmp/test/file && sync >> >> ================================================================== >> kernel BUG at fs/ext4/mballoc.c:2029! >> invalid opcode: 0000 [#1] PREEMPT SMP PTI >> CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 >> RIP: 0010:mb_mark_used+0x358/0x370 >> [...] >> Call Trace: >> ext4_mb_use_best_found+0x56/0x140 >> ext4_mb_complex_scan_group+0x196/0x2f0 >> ext4_mb_regular_allocator+0xa92/0xf00 >> ext4_mb_new_blocks+0x302/0xbc0 >> ext4_ext_map_blocks+0x95a/0xef0 >> ext4_map_blocks+0x2b1/0x680 >> ext4_do_writepages+0x733/0xbd0 >> [...] >> ================================================================== >> >> In ext4_mb_normalize_group_request(): >> ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; >> >> Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned >> int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a >> negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). >> >> Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a >> value range of 0-INT_MAX to avoid the above problem. In addition to the >> mb_group_prealloc sysfs interface, the following interfaces also have uint >> to int conversions that result in overflows, and are also fixed. >> >> err_ratelimit_burst >> msg_ratelimit_burst >> warning_ratelimit_burst >> err_ratelimit_interval_ms >> msg_ratelimit_interval_ms >> warning_ratelimit_interval_ms >> mb_best_avail_max_trim_order >> >> CC: stable@vger.kernel.org >> Signed-off-by: Baokun Li <libaokun1@huawei.com> > I don't think you need to change s_mb_group_prealloc here and then restrict > it even further in the next patch. I'd just leave it alone here. Yes, we could put the next patch before this one, but using s_mb_group_prealloc as an example makes it easier to understand why the attr_pointer_pi case is added here.There are several other variables that don't have more convincing examples. > > Also I think that limiting mb_best_avail_max_trim_order to 64 instead of > INT_MAX will make us more resilient to surprises in the future :) But I > don't really insist. > > Honza I think it's enough here to make sure that mb_best_avail_max_trim_order is a positive number, since we always make sure that min_order is not less than 0, as follows: order = fls(ac->ac_g_ex.fe_len) - 1; min_order = order - sbi->s_mb_best_avail_max_trim_order; if (min_order < 0) min_order = 0; An oversized mb_best_avail_max_trim_order can be interpreted as always being CR_ANY_FREE. 😄 >> --- >> fs/ext4/sysfs.c | 25 +++++++++++++++++-------- >> 1 file changed, 17 insertions(+), 8 deletions(-) >> >> diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c >> index a5d657fa05cb..6f9f96e00f2f 100644 >> --- a/fs/ext4/sysfs.c >> +++ b/fs/ext4/sysfs.c >> @@ -30,6 +30,7 @@ typedef enum { >> attr_first_error_time, >> attr_last_error_time, >> attr_feature, >> + attr_pointer_pi, >> attr_pointer_ui, >> attr_pointer_ul, >> attr_pointer_u64, >> @@ -178,6 +179,9 @@ static struct ext4_attr ext4_attr_##_name = { \ >> #define EXT4_RO_ATTR_ES_STRING(_name,_elname,_size) \ >> EXT4_ATTR_STRING(_name, 0444, _size, ext4_super_block, _elname) >> >> +#define EXT4_RW_ATTR_SBI_PI(_name,_elname) \ >> + EXT4_ATTR_OFFSET(_name, 0644, pointer_pi, ext4_sb_info, _elname) >> + >> #define EXT4_RW_ATTR_SBI_UI(_name,_elname) \ >> EXT4_ATTR_OFFSET(_name, 0644, pointer_ui, ext4_sb_info, _elname) >> >> @@ -213,17 +217,17 @@ 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_PI(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); >> -EXT4_RW_ATTR_SBI_UI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); >> -EXT4_RW_ATTR_SBI_UI(err_ratelimit_burst, s_err_ratelimit_state.burst); >> -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); >> -EXT4_RW_ATTR_SBI_UI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); >> -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); >> -EXT4_RW_ATTR_SBI_UI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); >> -EXT4_RW_ATTR_SBI_UI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); >> +EXT4_RW_ATTR_SBI_PI(err_ratelimit_interval_ms, s_err_ratelimit_state.interval); >> +EXT4_RW_ATTR_SBI_PI(err_ratelimit_burst, s_err_ratelimit_state.burst); >> +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_interval_ms, s_warning_ratelimit_state.interval); >> +EXT4_RW_ATTR_SBI_PI(warning_ratelimit_burst, s_warning_ratelimit_state.burst); >> +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_interval_ms, s_msg_ratelimit_state.interval); >> +EXT4_RW_ATTR_SBI_PI(msg_ratelimit_burst, s_msg_ratelimit_state.burst); >> +EXT4_RW_ATTR_SBI_PI(mb_best_avail_max_trim_order, s_mb_best_avail_max_trim_order); >> #ifdef CONFIG_EXT4_DEBUG >> EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail); >> #endif >> @@ -376,6 +380,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, >> >> switch (a->attr_id) { >> case attr_inode_readahead: >> + case attr_pointer_pi: >> case attr_pointer_ui: >> if (a->attr_ptr == ptr_ext4_super_block_offset) >> return sysfs_emit(buf, "%u\n", le32_to_cpup(ptr)); >> @@ -448,6 +453,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, >> return ret; >> >> switch (a->attr_id) { >> + case attr_pointer_pi: >> + if ((int)t < 0) >> + return -EINVAL; >> + fallthrough; >> case attr_pointer_ui: >> if (t != (unsigned int)t) >> return -EINVAL; >> -- >> 2.31.1 >> Thanks! -- With Best Regards, Baokun Li . ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow 2024-02-17 7:41 ` Baokun Li @ 2024-02-23 12:05 ` Jan Kara 2024-02-24 2:46 ` Baokun Li 0 siblings, 1 reply; 11+ messages in thread From: Jan Kara @ 2024-02-23 12:05 UTC (permalink / raw) To: Baokun Li Cc: Jan Kara, linux-ext4, tytso, adilger.kernel, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable On Sat 17-02-24 15:41:43, Baokun Li wrote: > On 2024/2/14 0:58, Jan Kara wrote: > > On Fri 26-01-24 16:57:13, Baokun Li wrote: > > > We can easily trigger a BUG_ON by using the following commands: > > > > > > mount /dev/$disk /tmp/test > > > echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc > > > echo test > /tmp/test/file && sync > > > > > > ================================================================== > > > kernel BUG at fs/ext4/mballoc.c:2029! > > > invalid opcode: 0000 [#1] PREEMPT SMP PTI > > > CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 > > > RIP: 0010:mb_mark_used+0x358/0x370 > > > [...] > > > Call Trace: > > > ext4_mb_use_best_found+0x56/0x140 > > > ext4_mb_complex_scan_group+0x196/0x2f0 > > > ext4_mb_regular_allocator+0xa92/0xf00 > > > ext4_mb_new_blocks+0x302/0xbc0 > > > ext4_ext_map_blocks+0x95a/0xef0 > > > ext4_map_blocks+0x2b1/0x680 > > > ext4_do_writepages+0x733/0xbd0 > > > [...] > > > ================================================================== > > > > > > In ext4_mb_normalize_group_request(): > > > ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; > > > > > > Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned > > > int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a > > > negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). > > > > > > Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a > > > value range of 0-INT_MAX to avoid the above problem. In addition to the > > > mb_group_prealloc sysfs interface, the following interfaces also have uint > > > to int conversions that result in overflows, and are also fixed. > > > > > > err_ratelimit_burst > > > msg_ratelimit_burst > > > warning_ratelimit_burst > > > err_ratelimit_interval_ms > > > msg_ratelimit_interval_ms > > > warning_ratelimit_interval_ms > > > mb_best_avail_max_trim_order > > > > > > CC: stable@vger.kernel.org > > > Signed-off-by: Baokun Li <libaokun1@huawei.com> > > I don't think you need to change s_mb_group_prealloc here and then restrict > > it even further in the next patch. I'd just leave it alone here. > Yes, we could put the next patch before this one, but using > s_mb_group_prealloc as an example makes it easier to understand > why the attr_pointer_pi case is added here.There are several other > variables that don't have more convincing examples. Yes, I think reordering would be good. Because I've read the convertion and started wondering: "is this enough?" > > Also I think that limiting mb_best_avail_max_trim_order to 64 instead of > > INT_MAX will make us more resilient to surprises in the future :) But I > > don't really insist. > > > > Honza > I think it's enough here to make sure that mb_best_avail_max_trim_order > is a positive number, since we always make sure that min_order > is not less than 0, as follows: > > order = fls(ac->ac_g_ex.fe_len) - 1; > min_order = order - sbi->s_mb_best_avail_max_trim_order; > if (min_order < 0) > min_order = 0; > > An oversized mb_best_avail_max_trim_order can be interpreted as > always being CR_ANY_FREE. 😄 Well, s_mb_best_avail_max_trim_order is not about allocation passes but about how many times are we willing to shorten the goal extent to half and still use the advanced free blocks search. And I agree that the mballoc code is careful enough that large numbers don't matter there but still why allowing storing garbage values? It is nicer to tell sysadmin he did something wrong right away. Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow 2024-02-23 12:05 ` Jan Kara @ 2024-02-24 2:46 ` Baokun Li 0 siblings, 0 replies; 11+ messages in thread From: Baokun Li @ 2024-02-24 2:46 UTC (permalink / raw) To: Jan Kara Cc: linux-ext4, tytso, adilger.kernel, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable, Baokun Li On 2024/2/23 20:05, Jan Kara wrote: > On Sat 17-02-24 15:41:43, Baokun Li wrote: >> On 2024/2/14 0:58, Jan Kara wrote: >>> On Fri 26-01-24 16:57:13, Baokun Li wrote: >>>> We can easily trigger a BUG_ON by using the following commands: >>>> >>>> mount /dev/$disk /tmp/test >>>> echo 2147483650 > /sys/fs/ext4/$disk/mb_group_prealloc >>>> echo test > /tmp/test/file && sync >>>> >>>> ================================================================== >>>> kernel BUG at fs/ext4/mballoc.c:2029! >>>> invalid opcode: 0000 [#1] PREEMPT SMP PTI >>>> CPU: 3 PID: 320 Comm: kworker/u36:1 Not tainted 6.8.0-rc1 #462 >>>> RIP: 0010:mb_mark_used+0x358/0x370 >>>> [...] >>>> Call Trace: >>>> ext4_mb_use_best_found+0x56/0x140 >>>> ext4_mb_complex_scan_group+0x196/0x2f0 >>>> ext4_mb_regular_allocator+0xa92/0xf00 >>>> ext4_mb_new_blocks+0x302/0xbc0 >>>> ext4_ext_map_blocks+0x95a/0xef0 >>>> ext4_map_blocks+0x2b1/0x680 >>>> ext4_do_writepages+0x733/0xbd0 >>>> [...] >>>> ================================================================== >>>> >>>> In ext4_mb_normalize_group_request(): >>>> ac->ac_g_ex.fe_len = EXT4_SB(sb)->s_mb_group_prealloc; >>>> >>>> Here fe_len is of type int, but s_mb_group_prealloc is of type unsigned >>>> int, so setting s_mb_group_prealloc to 2147483650 overflows fe_len to a >>>> negative number, which ultimately triggers a BUG_ON() in mb_mark_used(). >>>> >>>> Therefore, we add attr_pointer_pi (aka positive int attr pointer) with a >>>> value range of 0-INT_MAX to avoid the above problem. In addition to the >>>> mb_group_prealloc sysfs interface, the following interfaces also have uint >>>> to int conversions that result in overflows, and are also fixed. >>>> >>>> err_ratelimit_burst >>>> msg_ratelimit_burst >>>> warning_ratelimit_burst >>>> err_ratelimit_interval_ms >>>> msg_ratelimit_interval_ms >>>> warning_ratelimit_interval_ms >>>> mb_best_avail_max_trim_order >>>> >>>> CC: stable@vger.kernel.org >>>> Signed-off-by: Baokun Li <libaokun1@huawei.com> >>> I don't think you need to change s_mb_group_prealloc here and then restrict >>> it even further in the next patch. I'd just leave it alone here. >> Yes, we could put the next patch before this one, but using >> s_mb_group_prealloc as an example makes it easier to understand >> why the attr_pointer_pi case is added here.There are several other >> variables that don't have more convincing examples. > Yes, I think reordering would be good. Because I've read the convertion and > started wondering: "is this enough?" Well, I will put the next patch before this one in the next version. >>> Also I think that limiting mb_best_avail_max_trim_order to 64 instead of >>> INT_MAX will make us more resilient to surprises in the future :) But I >>> don't really insist. >>> >>> Honza >> I think it's enough here to make sure that mb_best_avail_max_trim_order >> is a positive number, since we always make sure that min_order >> is not less than 0, as follows: >> >> order = fls(ac->ac_g_ex.fe_len) - 1; >> min_order = order - sbi->s_mb_best_avail_max_trim_order; >> if (min_order < 0) >> min_order = 0; >> >> An oversized mb_best_avail_max_trim_order can be interpreted as >> always being CR_ANY_FREE. 😄 > Well, s_mb_best_avail_max_trim_order is not about allocation passes but > about how many times are we willing to shorten the goal extent to half and > still use the advanced free blocks search. Yes, this means that in CR1.5, in case the original request is satisfied, we allow allocation of blocks with an order of (goal_extent_order - s_mb_best_avail_max_trim_order) to accelerate block allocation. > And I agree that the mballoc > code is careful enough that large numbers don't matter there but still why > allowing storing garbage values? It is nicer to tell sysadmin he did > something wrong right away. > > Honza Yes, we shouldn't allow storing rubbish values, otherwise it may mislead admins, I will add an extra type to check it. Thanks! -- With Best Regards, Baokun Li . ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() [not found] <20240126085716.1363019-1-libaokun1@huawei.com> 2024-01-26 8:57 ` [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow Baokun Li @ 2024-01-26 8:57 ` Baokun Li 2024-01-27 2:09 ` Zhang Yi ` (2 more replies) 1 sibling, 3 replies; 11+ messages in thread From: Baokun Li @ 2024-01-26 8:57 UTC (permalink / raw) To: linux-ext4 Cc: tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, libaokun1, stable 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. Therefore it is not allowed to set s_mb_group_prealloc to a value greater than s_clusters_per_group via sysfs, and to avoid returning an order from mb_avg_fragment_size_order() that is greater than MB_NUM_ORDERS(sb). Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)") CC: stable@vger.kernel.org Signed-off-by: Baokun Li <libaokun1@huawei.com> --- fs/ext4/mballoc.c | 2 ++ fs/ext4/sysfs.c | 9 ++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f44f668e407f..1ea6491b6b00 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -832,6 +832,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; } diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c index 6f9f96e00f2f..60ca7b2797b2 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_group_prealloc, attr_feature, attr_pointer_pi, attr_pointer_ui, @@ -211,13 +212,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, group_prealloc, + 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_PI(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); @@ -380,6 +382,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, switch (a->attr_id) { case attr_inode_readahead: + case attr_group_prealloc: case attr_pointer_pi: case attr_pointer_ui: if (a->attr_ptr == ptr_ext4_super_block_offset) @@ -453,6 +456,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, return ret; switch (a->attr_id) { + case attr_group_prealloc: + if (t > sbi->s_clusters_per_group) + return -EINVAL; + fallthrough; case attr_pointer_pi: if ((int)t < 0) return -EINVAL; -- 2.31.1 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() 2024-01-26 8:57 ` [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() Baokun Li @ 2024-01-27 2:09 ` Zhang Yi 2024-02-13 16:14 ` Jan Kara 2024-02-20 5:39 ` Ojaswin Mujoo 2 siblings, 0 replies; 11+ messages in thread From: Zhang Yi @ 2024-01-27 2:09 UTC (permalink / raw) To: Baokun Li, linux-ext4 Cc: tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yangerkun, chengzhihao1, yukuai3, stable On 2024/1/26 16:57, Baokun Li wrote: > 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. > > Therefore it is not allowed to set s_mb_group_prealloc to a value greater > than s_clusters_per_group via sysfs, and to avoid returning an order from > mb_avg_fragment_size_order() that is greater than MB_NUM_ORDERS(sb). > > Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)") > CC: stable@vger.kernel.org > Signed-off-by: Baokun Li <libaokun1@huawei.com> Looks good to me. Reviewed-by: Zhang Yi <yi.zhang@huawei.com> > --- > fs/ext4/mballoc.c | 2 ++ > fs/ext4/sysfs.c | 9 ++++++++- > 2 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c > index f44f668e407f..1ea6491b6b00 100644 > --- a/fs/ext4/mballoc.c > +++ b/fs/ext4/mballoc.c > @@ -832,6 +832,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; > } > > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c > index 6f9f96e00f2f..60ca7b2797b2 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_group_prealloc, > attr_feature, > attr_pointer_pi, > attr_pointer_ui, > @@ -211,13 +212,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, group_prealloc, > + 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_PI(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); > @@ -380,6 +382,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, > > switch (a->attr_id) { > case attr_inode_readahead: > + case attr_group_prealloc: > case attr_pointer_pi: > case attr_pointer_ui: > if (a->attr_ptr == ptr_ext4_super_block_offset) > @@ -453,6 +456,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, > return ret; > > switch (a->attr_id) { > + case attr_group_prealloc: > + if (t > sbi->s_clusters_per_group) > + return -EINVAL; > + fallthrough; > case attr_pointer_pi: > if ((int)t < 0) > return -EINVAL; > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() 2024-01-26 8:57 ` [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() Baokun Li 2024-01-27 2:09 ` Zhang Yi @ 2024-02-13 16:14 ` Jan Kara 2024-02-20 5:39 ` Ojaswin Mujoo 2 siblings, 0 replies; 11+ messages in thread From: Jan Kara @ 2024-02-13 16:14 UTC (permalink / raw) To: Baokun Li Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable On Fri 26-01-24 16:57:14, Baokun Li wrote: > 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. > > Therefore it is not allowed to set s_mb_group_prealloc to a value greater > than s_clusters_per_group via sysfs, and to avoid returning an order from > mb_avg_fragment_size_order() that is greater than MB_NUM_ORDERS(sb). > > Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)") > CC: stable@vger.kernel.org > Signed-off-by: Baokun Li <libaokun1@huawei.com> Looks good. Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/ext4/mballoc.c | 2 ++ > fs/ext4/sysfs.c | 9 ++++++++- > 2 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c > index f44f668e407f..1ea6491b6b00 100644 > --- a/fs/ext4/mballoc.c > +++ b/fs/ext4/mballoc.c > @@ -832,6 +832,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; > } > > diff --git a/fs/ext4/sysfs.c b/fs/ext4/sysfs.c > index 6f9f96e00f2f..60ca7b2797b2 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_group_prealloc, > attr_feature, > attr_pointer_pi, > attr_pointer_ui, > @@ -211,13 +212,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, group_prealloc, > + 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_PI(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); > @@ -380,6 +382,7 @@ static ssize_t ext4_generic_attr_show(struct ext4_attr *a, > > switch (a->attr_id) { > case attr_inode_readahead: > + case attr_group_prealloc: > case attr_pointer_pi: > case attr_pointer_ui: > if (a->attr_ptr == ptr_ext4_super_block_offset) > @@ -453,6 +456,10 @@ static ssize_t ext4_generic_attr_store(struct ext4_attr *a, > return ret; > > switch (a->attr_id) { > + case attr_group_prealloc: > + if (t > sbi->s_clusters_per_group) > + return -EINVAL; > + fallthrough; > case attr_pointer_pi: > if ((int)t < 0) > return -EINVAL; > -- > 2.31.1 > -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() 2024-01-26 8:57 ` [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() Baokun Li 2024-01-27 2:09 ` Zhang Yi 2024-02-13 16:14 ` Jan Kara @ 2024-02-20 5:39 ` Ojaswin Mujoo 2024-02-20 6:31 ` Baokun Li 2 siblings, 1 reply; 11+ messages in thread From: Ojaswin Mujoo @ 2024-02-20 5:39 UTC (permalink / raw) To: Baokun Li Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable On Fri, Jan 26, 2024 at 04:57:14PM +0800, Baokun Li wrote: Hey Baokun, Good catch! I've added some minor comments below. Other than that feel free to add Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> > 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. > > Therefore it is not allowed to set s_mb_group_prealloc to a value greater > than s_clusters_per_group via sysfs, and to avoid returning an order from > mb_avg_fragment_size_order() that is greater than MB_NUM_ORDERS(sb). > > Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)") > CC: stable@vger.kernel.org > Signed-off-by: Baokun Li <libaokun1@huawei.com> > --- > fs/ext4/mballoc.c | 2 ++ > fs/ext4/sysfs.c | 9 ++++++++- > 2 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c > index f44f668e407f..1ea6491b6b00 100644 > --- a/fs/ext4/mballoc.c > +++ b/fs/ext4/mballoc.c > @@ -832,6 +832,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; > } So along with this change, I think it'll also be good to add an extra check in ext4_mb_choose_next_group_best_avail() as: if (1 << min_order < ac->ac_o_ex.fe_len) min_order = fls(ac->ac_o_ex.fe_len); + if (order >= MB_NUM_ORDERS(ac->ac_sb)) + order = MB_NUM_ORDERS(ac->ac_sb) - 1; + for (i = order; i >= min_order; i--) { int frag_order; /* The reason for this is that otherwise when order is large eg 29, we would unnecessarily loop from i=29 to i=13 while always looking at the same avg_fragment_list[13]. Regards, ojaswin ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() 2024-02-20 5:39 ` Ojaswin Mujoo @ 2024-02-20 6:31 ` Baokun Li 0 siblings, 0 replies; 11+ messages in thread From: Baokun Li @ 2024-02-20 6:31 UTC (permalink / raw) To: Ojaswin Mujoo Cc: linux-ext4, tytso, adilger.kernel, jack, ritesh.list, linux-kernel, yi.zhang, yangerkun, chengzhihao1, yukuai3, stable, Baokun Li On 2024/2/20 13:39, Ojaswin Mujoo wrote: > On Fri, Jan 26, 2024 at 04:57:14PM +0800, Baokun Li wrote: > > Hey Baokun, > > Good catch! I've added some minor comments below. Other than that feel > free to add > > Reviewed-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> > >> 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. >> >> Therefore it is not allowed to set s_mb_group_prealloc to a value greater >> than s_clusters_per_group via sysfs, and to avoid returning an order from >> mb_avg_fragment_size_order() that is greater than MB_NUM_ORDERS(sb). >> >> Fixes: 7e170922f06b ("ext4: Add allocation criteria 1.5 (CR1_5)") >> CC: stable@vger.kernel.org >> Signed-off-by: Baokun Li <libaokun1@huawei.com> >> --- >> fs/ext4/mballoc.c | 2 ++ >> fs/ext4/sysfs.c | 9 ++++++++- >> 2 files changed, 10 insertions(+), 1 deletion(-) >> >> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c >> index f44f668e407f..1ea6491b6b00 100644 >> --- a/fs/ext4/mballoc.c >> +++ b/fs/ext4/mballoc.c >> @@ -832,6 +832,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; >> } > So along with this change, I think it'll also be good to add an extra > check in ext4_mb_choose_next_group_best_avail() as: > > if (1 << min_order < ac->ac_o_ex.fe_len) > min_order = fls(ac->ac_o_ex.fe_len); > > + if (order >= MB_NUM_ORDERS(ac->ac_sb)) > + order = MB_NUM_ORDERS(ac->ac_sb) - 1; > + > for (i = order; i >= min_order; i--) { > int frag_order; > /* > > > The reason for this is that otherwise when order is large eg 29, > we would unnecessarily loop from i=29 to i=13 while always > looking at the same avg_fragment_list[13]. > > Regards, > ojaswin Yeah, good point! This will cut down on some unnecessary loops. I'll add this extra check in the next version. Thanks for having a look! -- With Best Regards, Baokun Li . ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2024-02-24 2:46 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20240126085716.1363019-1-libaokun1@huawei.com>
2024-01-26 8:57 ` [PATCH 4/7] ext4: add positive int attr pointer to avoid sysfs variables overflow Baokun Li
2024-01-27 2:07 ` Zhang Yi
2024-02-13 16:58 ` Jan Kara
2024-02-17 7:41 ` Baokun Li
2024-02-23 12:05 ` Jan Kara
2024-02-24 2:46 ` Baokun Li
2024-01-26 8:57 ` [PATCH 5/7] ext4: fix slab-out-of-bounds in ext4_mb_find_good_group_avg_frag_lists() Baokun Li
2024-01-27 2:09 ` Zhang Yi
2024-02-13 16:14 ` Jan Kara
2024-02-20 5:39 ` Ojaswin Mujoo
2024-02-20 6:31 ` Baokun Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox