Commit b4f35754 authored by Chao Yu's avatar Chao Yu Committed by Zheng Zucheng
Browse files

f2fs: check validation of fault attrs in f2fs_build_fault_attr()

stable inclusion
from stable-v6.6.39
commit 44958ca9e400f57bd0478115519ffc350fcee61e
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAGS16
CVE: CVE-2024-42160

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=44958ca9e400f57bd0478115519ffc350fcee61e



--------------------------------

[ Upstream commit 4ed886b187f47447ad559619c48c086f432d2b77 ]

- It missed to check validation of fault attrs in parse_options(),
let's fix to add check condition in f2fs_build_fault_attr().
- Use f2fs_build_fault_attr() in __sbi_store() to clean up code.

Signed-off-by: default avatarChao Yu <chao@kernel.org>
Signed-off-by: default avatarJaegeuk Kim <jaegeuk@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>

Conflicts:
    fs/f2fs/sysfs.c
    fs/f2fs/super.c
[Some contexts different. No functional impact.]
Signed-off-by: default avatarZheng Zucheng <zhengzucheng@huawei.com>
parent f833e83b
Loading
Loading
Loading
Loading
+8 −4
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ enum {

struct f2fs_fault_info {
	atomic_t inject_ops;
	unsigned int inject_rate;
	int inject_rate;
	unsigned int inject_type;
};

@@ -4115,10 +4115,14 @@ static inline bool f2fs_force_buffered_io(struct inode *inode,
}

#ifdef CONFIG_F2FS_FAULT_INJECTION
extern void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
							unsigned int type);
extern int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
							unsigned long type);
#else
#define f2fs_build_fault_attr(sbi, rate, type)		do { } while (0)
static int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
							unsigned long type)
{
	return 0;
}
#endif

static inline bool is_journalled_quota(struct f2fs_sb_info *sbi)
+20 −7
Original line number Diff line number Diff line
@@ -58,21 +58,31 @@ const char *f2fs_fault_name[FAULT_MAX] = {
	[FAULT_WRITE_IO]	= "write IO error",
};

void f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned int rate,
							unsigned int type)
int f2fs_build_fault_attr(struct f2fs_sb_info *sbi, unsigned long rate,
							unsigned long type)
{
	struct f2fs_fault_info *ffi = &F2FS_OPTION(sbi).fault_info;

	if (rate) {
		if (rate > INT_MAX)
			return -EINVAL;
		atomic_set(&ffi->inject_ops, 0);
		ffi->inject_rate = rate;
		ffi->inject_rate = (int)rate;
	}

	if (type)
		ffi->inject_type = type;
	if (type) {
		if (type >= BIT(FAULT_MAX))
			return -EINVAL;
		ffi->inject_type = (unsigned int)type;
	}

	if (!rate && !type)
		memset(ffi, 0, sizeof(struct f2fs_fault_info));
	else
		f2fs_info(sbi,
			"build fault injection attr: rate: %lu, type: 0x%lx",
								rate, type);
	return 0;
}
#endif

@@ -728,14 +738,17 @@ static int parse_options(struct super_block *sb, char *options, bool is_remount)
		case Opt_fault_injection:
			if (args->from && match_int(args, &arg))
				return -EINVAL;
			f2fs_build_fault_attr(sbi, arg, F2FS_ALL_FAULT_TYPE);
			if (f2fs_build_fault_attr(sbi, arg,
					F2FS_ALL_FAULT_TYPE))
				return -EINVAL;
			set_opt(sbi, FAULT_INJECTION);
			break;

		case Opt_fault_type:
			if (args->from && match_int(args, &arg))
				return -EINVAL;
			f2fs_build_fault_attr(sbi, 0, arg);
			if (f2fs_build_fault_attr(sbi, 0, arg))
				return -EINVAL;
			set_opt(sbi, FAULT_INJECTION);
			break;
#else
+10 −4
Original line number Diff line number Diff line
@@ -322,10 +322,16 @@ static ssize_t __sbi_store(struct f2fs_attr *a,
	if (ret < 0)
		return ret;
#ifdef CONFIG_F2FS_FAULT_INJECTION
	if (a->struct_type == FAULT_INFO_TYPE && t >= (1 << FAULT_MAX))
	if (a->struct_type == FAULT_INFO_TYPE) {
		if (f2fs_build_fault_attr(sbi, 0, t))
			return -EINVAL;
	if (a->struct_type == FAULT_INFO_RATE && t >= UINT_MAX)
		return count;
	}
	if (a->struct_type == FAULT_INFO_RATE) {
		if (f2fs_build_fault_attr(sbi, t, 0))
			return -EINVAL;
		return count;
	}
#endif
	if (a->struct_type == RESERVED_BLOCKS) {
		spin_lock(&sbi->stat_lock);