Unverified Commit 24edcc2c authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10083 CVE-2024-40955

Merge Pull Request from: @ci-robot 
 
PR sync from: Yifan Qiao <qiaoyifan4@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/YE4EKXLYD4X2TXROY6ZH5NDXSGII43EG/ 
Baokun Li (9):
  ext4: avoid overflow when setting values via sysfs
  ext4: refactor out ext4_generic_attr_store()
  ext4: refactor out ext4_generic_attr_show()
  ext4: fix slab-out-of-bounds in
    ext4_mb_find_good_group_avg_frag_lists()
  ext4: add new attr pointer attr_mb_order
  ext4: add positive int attr pointer to avoid sysfs variables overflow
  ext4: set type of ac_groups_linear_remaining to __u32 to avoid
    overflow
  ext4: set the type of max_zeroout to unsigned int to avoid overflow
  ext4: clean up s_mb_rb_lock to fix build warnings with C=1


-- 
2.39.2
 
https://gitee.com/src-openeuler/kernel/issues/IAD018 
 
Link:https://gitee.com/openeuler/kernel/pulls/10083

 

Reviewed-by: default avatarZhang Peng <zhangpeng362@huawei.com>
Signed-off-by: default avatarZhang Peng <zhangpeng362@huawei.com>
parents 12bf91b0 4bf3e5de
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -3413,9 +3413,10 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
	struct ext4_extent *ex, *abut_ex;
	ext4_lblk_t ee_block, eof_block;
	unsigned int ee_len, depth, map_len = map->m_len;
	int allocated = 0, max_zeroout = 0;
	int err = 0;
	int split_flag = EXT4_EXT_DATA_VALID2;
	int allocated = 0;
	unsigned int max_zeroout = 0;

	ext_debug(inode, "logical block %llu, max_blocks %u\n",
		  (unsigned long long)map->m_lblk, map_len);
+4 −1
Original line number Diff line number Diff line
@@ -834,6 +834,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;
}

@@ -1011,6 +1013,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;
@@ -3190,7 +3194,6 @@ int ext4_seq_mb_stats_show(struct seq_file *seq, void *offset)
}

static void *ext4_mb_seq_structs_summary_start(struct seq_file *seq, loff_t *pos)
__acquires(&EXT4_SB(sb)->s_mb_rb_lock)
{
	struct super_block *sb = pde_data(file_inode(seq->file));
	unsigned long position;
+1 −1
Original line number Diff line number Diff line
@@ -194,8 +194,8 @@ struct ext4_allocation_context {

	__u32 ac_groups_considered;
	__u32 ac_flags;		/* allocation hints */
	__u32 ac_groups_linear_remaining;
	__u16 ac_groups_scanned;
	__u16 ac_groups_linear_remaining;
	__u16 ac_found;
	__u16 ac_cX_found[EXT4_MB_NUM_CRS];
	__u16 ac_tail;
+105 −69
Original line number Diff line number Diff line
@@ -29,7 +29,10 @@ typedef enum {
	attr_trigger_test_error,
	attr_first_error_time,
	attr_last_error_time,
	attr_clusters_in_group,
	attr_mb_order,
	attr_feature,
	attr_pointer_pi,
	attr_pointer_ui,
	attr_pointer_ul,
	attr_pointer_u64,
@@ -104,7 +107,7 @@ static ssize_t reserved_clusters_store(struct ext4_sb_info *sbi,
	int ret;

	ret = kstrtoull(skip_spaces(buf), 0, &val);
	if (ret || val >= clusters)
	if (ret || val >= clusters || (s64)val < 0)
		return -EINVAL;

	atomic64_set(&sbi->s_resv_clusters, val);
@@ -178,6 +181,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)

@@ -207,23 +213,25 @@ 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_ATTR_OFFSET(mb_best_avail_max_trim_order, 0644, mb_order,
		 ext4_sb_info, s_mb_best_avail_max_trim_order);
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);
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);
#ifdef CONFIG_EXT4_DEBUG
EXT4_RW_ATTR_SBI_UL(simulate_fail, s_simulate_fail);
#endif
@@ -366,13 +374,45 @@ static ssize_t __print_tstamp(char *buf, __le32 lo, __u8 hi)
#define print_tstamp(buf, es, tstamp) \
	__print_tstamp(buf, (es)->tstamp, (es)->tstamp ## _hi)

static ssize_t ext4_generic_attr_show(struct ext4_attr *a,
				      struct ext4_sb_info *sbi, char *buf)
{
	void *ptr = calc_ptr(a, sbi);

	if (!ptr)
		return 0;

	switch (a->attr_id) {
	case attr_inode_readahead:
	case attr_clusters_in_group:
	case attr_mb_order:
	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));
		return sysfs_emit(buf, "%u\n", *((unsigned int *) ptr));
	case attr_pointer_ul:
		return sysfs_emit(buf, "%lu\n", *((unsigned long *) ptr));
	case attr_pointer_u8:
		return sysfs_emit(buf, "%u\n", *((unsigned char *) ptr));
	case attr_pointer_u64:
		if (a->attr_ptr == ptr_ext4_super_block_offset)
			return sysfs_emit(buf, "%llu\n", le64_to_cpup(ptr));
		return sysfs_emit(buf, "%llu\n", *((unsigned long long *) ptr));
	case attr_pointer_string:
		return sysfs_emit(buf, "%.*s\n", a->attr_size, (char *) ptr);
	case attr_pointer_atomic:
		return sysfs_emit(buf, "%d\n", atomic_read((atomic_t *) ptr));
	}
	return 0;
}

static ssize_t ext4_attr_show(struct kobject *kobj,
			      struct attribute *attr, char *buf)
{
	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
						s_kobj);
	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
	void *ptr = calc_ptr(a, sbi);

	switch (a->attr_id) {
	case attr_delayed_allocation_blocks:
@@ -391,45 +431,6 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
		return sysfs_emit(buf, "%llu\n",
				(unsigned long long)
			percpu_counter_sum(&sbi->s_sra_exceeded_retry_limit));
	case attr_inode_readahead:
	case attr_pointer_ui:
		if (!ptr)
			return 0;
		if (a->attr_ptr == ptr_ext4_super_block_offset)
			return sysfs_emit(buf, "%u\n",
					le32_to_cpup(ptr));
		else
			return sysfs_emit(buf, "%u\n",
					*((unsigned int *) ptr));
	case attr_pointer_ul:
		if (!ptr)
			return 0;
		return sysfs_emit(buf, "%lu\n",
				*((unsigned long *) ptr));
	case attr_pointer_u8:
		if (!ptr)
			return 0;
		return sysfs_emit(buf, "%u\n",
				*((unsigned char *) ptr));
	case attr_pointer_u64:
		if (!ptr)
			return 0;
		if (a->attr_ptr == ptr_ext4_super_block_offset)
			return sysfs_emit(buf, "%llu\n",
					le64_to_cpup(ptr));
		else
			return sysfs_emit(buf, "%llu\n",
					*((unsigned long long *) ptr));
	case attr_pointer_string:
		if (!ptr)
			return 0;
		return sysfs_emit(buf, "%.*s\n", a->attr_size,
				(char *) ptr);
	case attr_pointer_atomic:
		if (!ptr)
			return 0;
		return sysfs_emit(buf, "%d\n",
				atomic_read((atomic_t *) ptr));
	case attr_feature:
		return sysfs_emit(buf, "supported\n");
	case attr_first_error_time:
@@ -438,29 +439,34 @@ static ssize_t ext4_attr_show(struct kobject *kobj,
		return print_tstamp(buf, sbi->s_es, s_last_error_time);
	case attr_journal_task:
		return journal_task_show(sbi, buf);
	default:
		return ext4_generic_attr_show(a, sbi, buf);
	}

	return 0;
}

static ssize_t ext4_attr_store(struct kobject *kobj,
			       struct attribute *attr,
static ssize_t ext4_generic_attr_store(struct ext4_attr *a,
				       struct ext4_sb_info *sbi,
				       const char *buf, size_t len)
{
	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
						s_kobj);
	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);
	void *ptr = calc_ptr(a, sbi);
	unsigned long t;
	int ret;
	unsigned int t;
	unsigned long lt;
	void *ptr = calc_ptr(a, sbi);

	switch (a->attr_id) {
	case attr_reserved_clusters:
		return reserved_clusters_store(sbi, buf, len);
	case attr_pointer_ui:
	if (!ptr)
		return 0;
		ret = kstrtoul(skip_spaces(buf), 0, &t);

	switch (a->attr_id) {
	case attr_pointer_pi:
		ret = kstrtouint(skip_spaces(buf), 0, &t);
		if (ret)
			return ret;
		if ((int)t < 0)
			return -EINVAL;
		*((unsigned int *) ptr) = t;
		return len;
	case attr_pointer_ui:
		ret = kstrtouint(skip_spaces(buf), 0, &t);
		if (ret)
			return ret;
		if (a->attr_ptr == ptr_ext4_super_block_offset)
@@ -468,20 +474,50 @@ static ssize_t ext4_attr_store(struct kobject *kobj,
		else
			*((unsigned int *) ptr) = t;
		return len;
	case attr_mb_order:
		ret = kstrtouint(skip_spaces(buf), 0, &t);
		if (ret)
			return ret;
		if (t > 64)
			return -EINVAL;
		*((unsigned int *) ptr) = t;
		return len;
	case attr_clusters_in_group:
		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;
		ret = kstrtoul(skip_spaces(buf), 0, &t);
		ret = kstrtoul(skip_spaces(buf), 0, &lt);
		if (ret)
			return ret;
		*((unsigned long *) ptr) = t;
		*((unsigned long *) ptr) = lt;
		return len;
	}
	return 0;
}

static ssize_t ext4_attr_store(struct kobject *kobj,
			       struct attribute *attr,
			       const char *buf, size_t len)
{
	struct ext4_sb_info *sbi = container_of(kobj, struct ext4_sb_info,
						s_kobj);
	struct ext4_attr *a = container_of(attr, struct ext4_attr, attr);

	switch (a->attr_id) {
	case attr_reserved_clusters:
		return reserved_clusters_store(sbi, buf, len);
	case attr_inode_readahead:
		return inode_readahead_blks_store(sbi, buf, len);
	case attr_trigger_test_error:
		return trigger_test_error(sbi, buf, len);
	default:
		return ext4_generic_attr_store(a, sbi, buf, len);
	}
	return 0;
}

static void ext4_sb_release(struct kobject *kobj)