[PATCH] firmware: arm_scmi: quirk: fix write to string constant
From: Johan Hovold <johan@kernel.org>
Date: 2025-08-29 13:23:38
Also in:
arm-scmi, lkml, stable
Subsystem:
system control & power/management interface (scpi/scmi) message protocol drivers, the rest · Maintainers:
Sudeep Holla, Linus Torvalds
The quirk version range is typically a string constant and must not be modified (e.g. as it may be stored in read-only memory): Unable to handle kernel write to read-only memory at virtual address ffffc036d998a947 Fix the range parsing so that it operates on a copy of the version range string, and mark all the quirk strings as const to reduce the risk of introducing similar future issues. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220437 Fixes: 487c407d57d6 ("firmware: arm_scmi: Add common framework to handle firmware quirks") Cc: stable@vger.kernel.org # 6.16 Cc: Cristian Marussi <cristian.marussi@arm.com> Signed-off-by: Johan Hovold <johan@kernel.org> --- drivers/firmware/arm_scmi/quirks.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/drivers/firmware/arm_scmi/quirks.c b/drivers/firmware/arm_scmi/quirks.c
index 03960aca3610..e70823754b0b 100644
--- a/drivers/firmware/arm_scmi/quirks.c
+++ b/drivers/firmware/arm_scmi/quirks.c@@ -89,9 +89,9 @@ struct scmi_quirk { bool enabled; const char *name; - char *vendor; - char *sub_vendor_id; - char *impl_ver_range; + const char *vendor; + const char *sub_vendor_id; + const char *impl_ver_range; u32 start_range; u32 end_range; struct static_key_false *key;
@@ -217,7 +217,7 @@ static unsigned int scmi_quirk_signature(const char *vend, const char *sub_vend) static int scmi_quirk_range_parse(struct scmi_quirk *quirk) { - const char *last, *first = quirk->impl_ver_range; + const char *last, *first; size_t len; char *sep; int ret;
@@ -228,8 +228,12 @@ static int scmi_quirk_range_parse(struct scmi_quirk *quirk) if (!len) return 0; + first = kmemdup(quirk->impl_ver_range, len + 1, GFP_KERNEL); + if (!first) + return -ENOMEM; + last = first + len - 1; - sep = strchr(quirk->impl_ver_range, '-'); + sep = strchr(first, '-'); if (sep) *sep = '\0';
@@ -238,7 +242,7 @@ static int scmi_quirk_range_parse(struct scmi_quirk *quirk) else /* X OR X- OR X-y */ ret = kstrtouint(first, 0, &quirk->start_range); if (ret) - return ret; + goto out_free; if (!sep) quirk->end_range = quirk->start_range;
@@ -246,7 +250,9 @@ static int scmi_quirk_range_parse(struct scmi_quirk *quirk) ret = kstrtouint(sep + 1, 0, &quirk->end_range); if (quirk->start_range > quirk->end_range) - return -EINVAL; + ret = -EINVAL; +out_free: + kfree(first); return ret; }
--
2.49.1