提交 2ac0cef4 编写于 作者: L Li Nan 提交者: Jialin Zhang

md/raid10: fix overflow in safe_delay_store

hulk inclusion
category: bugfix
bugzilla: 188284, https://gitee.com/openeuler/kernel/issues/I6ECB2
CVE: NA

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

There is no input check when echo md/safe_mode_delay, and overflow will
occur. There is risk of overflow in strict_strtoul_scaled(), too. Fixed
it by using kstrtoul instead of parsing word one by one.
Signed-off-by: NLi Nan <linan122@huawei.com>
Reviewed-by: NHou Tao <houtao1@huawei.com>
Signed-off-by: NJialin Zhang <zhangjialin11@huawei.com>
上级 5f254d2a
...@@ -3846,35 +3846,51 @@ static int analyze_sbs(struct mddev *mddev) ...@@ -3846,35 +3846,51 @@ static int analyze_sbs(struct mddev *mddev)
*/ */
int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale) int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
{ {
unsigned long result = 0; unsigned long result = 0, decimals = 0;
long decimals = -1; char *pos, *str;
while (isdigit(*cp) || (*cp == '.' && decimals < 0)) { int rv;
if (*cp == '.')
decimals = 0; str = kmemdup_nul(cp, strlen(cp), GFP_KERNEL);
else if (decimals < scale) { if (!str)
unsigned int value; return -ENOMEM;
value = *cp - '0'; pos = strchr(str, '.');
result = result * 10 + value; if (pos) {
if (decimals >= 0) int cnt = scale;
decimals++;
} *pos = '\0';
cp++; while (isdigit(*(++pos))) {
} if (cnt) {
if (*cp == '\n') decimals = decimals * 10 + *pos - '0';
cp++; cnt--;
if (*cp) }
}
if (*pos == '\n')
pos++;
if (*pos) {
kfree(str);
return -EINVAL;
}
decimals *= int_pow(10, cnt);
}
rv = kstrtoul(str, 10, &result);
kfree(str);
if (rv)
return rv;
if (result > (ULONG_MAX - decimals) / (unsigned int)int_pow(10, scale))
return -EINVAL; return -EINVAL;
if (decimals < 0) *res = result * int_pow(10, scale) + decimals;
decimals = 0;
*res = result * int_pow(10, scale - decimals); return rv;
return 0;
} }
static ssize_t static ssize_t
safe_delay_show(struct mddev *mddev, char *page) safe_delay_show(struct mddev *mddev, char *page)
{ {
int msec = (mddev->safemode_delay*1000)/HZ; unsigned int msec = ((unsigned long)mddev->safemode_delay*1000)/HZ;
return sprintf(page, "%d.%03d\n", msec/1000, msec%1000);
return sprintf(page, "%u.%03u\n", msec/1000, msec%1000);
} }
static ssize_t static ssize_t
safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
...@@ -3888,10 +3904,14 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len) ...@@ -3888,10 +3904,14 @@ safe_delay_store(struct mddev *mddev, const char *cbuf, size_t len)
if (strict_strtoul_scaled(cbuf, &msec, 3) < 0) if (strict_strtoul_scaled(cbuf, &msec, 3) < 0)
return -EINVAL; return -EINVAL;
if (msec > UINT_MAX)
return -EINVAL;
if (msec == 0) if (msec == 0)
mddev->safemode_delay = 0; mddev->safemode_delay = 0;
else { else {
unsigned long old_delay = mddev->safemode_delay; unsigned long old_delay = mddev->safemode_delay;
/* HZ <= 1000, so new_delay < UINT_MAX, too */
unsigned long new_delay = (msec*HZ)/1000; unsigned long new_delay = (msec*HZ)/1000;
if (new_delay == 0) if (new_delay == 0)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册