rasdaemon/bugfix-set-to-default-when-param-is-overflow.patch

137 lines
4.6 KiB
Diff
Raw Normal View History

2024-12-16 17:31:13 +08:00
From c306d693f86cd9e128a103b1670b653613eb78d2 Mon Sep 17 00:00:00 2001
From: luckky <guodashun1@huawei.com>
Date: Mon, 16 Dec 2024 17:20:04 +0800
Subject: [PATCH] bugfix set to default when param is overflow
1. In this patch, we check if the value is overflow before parsing the
value with its unit. we replaced sscanf with strtoul cause the strtoul
has clear errno ERANGE for overflow case.
2. When the value is overflow, the sscanf will produce Undefined Behavior
(https://man7.org/linux/man-pages/man3/sscanf.3.html#BUGS).
The final value after being truncated is confusing. So in this patch
we will set to default value when the value is overflow.
---
ras-page-isolation.c | 56 +++++++++++++++++++++++++++-----------------
1 file changed, 35 insertions(+), 21 deletions(-)
diff --git a/ras-page-isolation.c b/ras-page-isolation.c
index caa8c31..ed07b70 100644
--- a/ras-page-isolation.c
+++ b/ras-page-isolation.c
@@ -44,6 +44,7 @@ static struct isolation threshold = {
.units = threshold_units,
.env = "50",
.unit = "",
+ .val = 50,
};
static struct isolation cycle = {
@@ -51,6 +52,7 @@ static struct isolation cycle = {
.units = cycle_units,
.env = "24h",
.unit = "h",
+ .val = 86400,
};
static const char *kernel_offline[] = {
@@ -106,10 +108,24 @@ static void page_offline_init(void)
offline_choice[offline].name);
}
+/*
+ * The 'parse_isolation_env' will parse the real value from the env settings
+ * in config file. The valid format of the env is pure positive number
+ * (like '12345') or a positive number with specific units (like '24h').
+ * When the unit is not set, we use the default unit (threshold for '' and
+ * cycle for 'h').
+ * The number is only supported in decimal, while others will produce errors.
+ * This function will parse the high level units to base units (like 'h' is
+ * a high level unit and 's' is a base unit).
+ * The valid value range is [1, UNLONG_MAX], and when the value is out of
+ * range (whether the origin pure number without units or the parsed number
+ * with the base units), the value will be set to the default value.
+ */
static void parse_isolation_env(struct isolation *config)
{
char *env = getenv(config->name);
char *unit = NULL;
+ char *endptr = NULL;
const struct config *units = NULL;
int i, no_unit;
int valid = 0;
@@ -146,43 +162,41 @@ static void parse_isolation_env(struct isolation *config)
parse:
/* if invalid, use default env */
if (valid) {
- config->env = env;
if (!no_unit)
config->unit = unit;
} else {
+ env = config->env;
log(TERM, LOG_INFO, "Improper %s, set to default %s.\n",
config->name, config->env);
}
/* if env value string is greater than ulong_max, truncate the last digit */
- sscanf(config->env, "%lu", &value);
+ errno = 0;
+ value = strtoul(env, &endptr, 10);
+ if (errno == ERANGE)
+ config->overflow = true;
for (units = config->units; units->name; units++) {
if (!strcasecmp(config->unit, units->name))
unit_matched = 1;
if (unit_matched) {
tmp = value;
value *= units->val;
- if (tmp != 0 && value / tmp != units->val)
+ if (tmp != 0 && value / tmp != units->val) {
config->overflow = true;
+ break;
+ }
}
}
- config->val = value;
- /* In order to output value and unit perfectly */
- config->unit = no_unit ? config->unit : "";
-}
-
-static void parse_env_string(struct isolation *config, char *str, unsigned int size)
-{
- int i;
-
- if (config->overflow) {
- /* when overflow, use basic unit */
- for (i = 0; config->units[i].name; i++) ;
- snprintf(str, size, "%lu%s", config->val, config->units[i-1].name);
- log(TERM, LOG_INFO, "%s is set overflow(%s), truncate it\n",
- config->name, config->env);
+ if (!config->overflow) {
+ config->val = value;
+ config->env = env;
+ /* In order to output value and unit perfectly */
+ config->unit = no_unit ? config->unit : "";
} else {
- snprintf(str, size, "%s%s", config->env, config->unit);
+ log(TERM, LOG_INFO, "%s is set overflow(%s), set to default %s\n",
+ config->name, env, config->env);
+ /* In order to output value and unit perfectly */
+ config->unit = "";
}
}
@@ -199,8 +213,8 @@ static void page_isolation_init(void)
parse_isolation_env(&threshold);
parse_isolation_env(&cycle);
- parse_env_string(&threshold, threshold_string, sizeof(threshold_string));
- parse_env_string(&cycle, cycle_string, sizeof(cycle_string));
+ snprintf(threshold_string, sizeof(threshold_string), "%s%s", threshold.env, threshold.unit);
+ snprintf(cycle_string, sizeof(cycle_string), "%s%s", cycle.env, cycle.unit);
log(TERM, LOG_INFO, "Threshold of memory Corrected Errors is %s / %s\n",
threshold_string, cycle_string);
}
--
2.43.0