diff --git a/fix-parse-param-bug-and-set-default-when-overflow.patch b/fix-parse-param-bug-and-set-default-when-overflow.patch new file mode 100644 index 0000000000000000000000000000000000000000..aff861815e7f60ab66c8c1f1be7083825695b978 --- /dev/null +++ b/fix-parse-param-bug-and-set-default-when-overflow.patch @@ -0,0 +1,151 @@ +From 2780e4dca228b82d185ccf78e0bcc69ba7a3b996 Mon Sep 17 00:00:00 2001 +From: luckky +Date: Mon, 16 Dec 2024 16:46:44 +0800 +Subject: [PATCH] fix parse param bug and set default when 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. In this patch, we deleted the wrong logic unit_matched=0. When we + set the param with a high level unit (e.g. PAGE_CE_THRESHOLD=1m), + the real value we expect is 1000000(1*1000*1000), but now we only + match the unit 'm' and multiply 1000 once, so the value we get is + 1000 rather than 1000000. In this patch we fix the bug. +3. 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 | 65 +++++++++++++++++++++++--------------------- + 1 file changed, 34 insertions(+), 31 deletions(-) + +diff --git a/ras-page-isolation.c b/ras-page-isolation.c +index 6fe8f80..202132a 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,54 +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; +- /** +- * if units->val is 1, config->env is greater than ulong_max, so it is can strtoul +- * if failed, the value is greater than ulong_max, set config->overflow = true +- */ +- if (units->val == 1) { +- char *endptr; +- unsigned long converted_value = strtoul(config->env, &endptr, 10); +- if (errno == ERANGE || *endptr != '\0') +- config->overflow = true; ++ break; + } +- unit_matched = 0; + } + } +- 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 = ""; + } + } + +@@ -210,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 + diff --git a/rasdaemon.spec b/rasdaemon.spec index 9e06d22f6cc6c2aa149b481a84315c46b976924c..af8cb25ad16a567cb88d6d55fddaf3d8fd436595 100644 --- a/rasdaemon.spec +++ b/rasdaemon.spec @@ -1,6 +1,6 @@ Name: rasdaemon Version: 0.8.0 -Release: 8 +Release: 9 License: GPLv2 Summary: Utility to get Platform Reliability, Availability and Serviceability (RAS) reports via the Kernel tracing events URL: https://github.com/mchehab/rasdaemon.git @@ -38,6 +38,7 @@ Patch9011: backport-ras-events-quit-loop-in-read_ras_event-when-kbuf-data-is-bro Patch9012: backport-Rasdaemon-Fix-autoreconf-build-error.patch Patch9013: backport-mce-amd-smca-update-smca_hwid-to-use-smca_bank_types.patch Patch9014: backport-Fix-the-bug-that-config-env-is-greater-than-ulong_ma.patch +Patch9015: fix-parse-param-bug-and-set-default-when-overflow.patch %description The rasdaemon program is a daemon which monitors the platform @@ -89,6 +90,12 @@ fi /usr/bin/systemctl disable rasdaemon.service >/dev/null 2>&1 || : %changelog +* Mon Dec 16 2024 guodashun - 0.8.0-9 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC: fix parse param bug and set default when overflow + * Mon Dec 2 2024 guodashun - 0.8.0-8 - Type:bugfix - CVE:NA