]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
firmware: arm_scmi: quirk: Prevent writes to string constants
authorJohan Hovold <johan@kernel.org>
Fri, 29 Aug 2025 13:21:52 +0000 (15:21 +0200)
committerSudeep Holla <sudeep.holla@arm.com>
Tue, 2 Sep 2025 10:23:42 +0000 (11:23 +0100)
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). Attempting
to do so can trigger faults such as:

  |  Unable to handle kernel write to read-only memory at virtual
  |  address ffffc036d998a947

Update 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>
Reported-by: Jan Palus <jpalus@fastmail.com>
Signed-off-by: Johan Hovold <johan@kernel.org>
Message-Id: <20250829132152.28218-1-johan@kernel.org>
[sudeep.holla: minor commit message rewording; switch to cleanup helpers]
Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
drivers/firmware/arm_scmi/quirks.c

index 03960aca3610012d11b56471afe1ce4915029d4d..03848283c2a07b7281e0a94506e81e642e21760f 100644 (file)
@@ -71,6 +71,7 @@
  */
 
 #include <linux/ctype.h>
+#include <linux/cleanup.h>
 #include <linux/device.h>
 #include <linux/export.h>
 #include <linux/hashtable.h>
@@ -89,9 +90,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 +218,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 __free(kfree) = NULL;
        size_t len;
        char *sep;
        int ret;
@@ -228,8 +229,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';