platform/x86: thinkpad_acpi: replace deprecated strncpy with memcpy
authorJustin Stitt <justinstitt@google.com>
Fri, 20 Oct 2023 17:52:43 +0000 (17:52 +0000)
committerIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 23 Oct 2023 13:58:21 +0000 (16:58 +0300)
commit942a4a61b64e182d756a1a5776aa500d3b3d862f
tree547d6dcabd90fd7efff5eda42699dd2de9b58a01
parente485c7a1939d9b1e6ed2a728e15009b44074f131
platform/x86: thinkpad_acpi: replace deprecated strncpy with memcpy

strncpy() is deprecated for use on NUL-terminated destination strings
[1] and as such we should prefer more robust and less ambiguous
interfaces.

We expect ec_fw_string to be NUL-terminated based on its use with format
strings in thinkpad_acpi.c:
11241 | pr_notice("ThinkPad firmware release %s doesn't match the known patterns\n",
11242 |     ec_fw_string);

Moreover, NUL-padding is not required since ec_fw_string is explicitly
zero-initialized:
11185 | char ec_fw_string[18] = {0};

When carefully copying bytes from one buffer to another in
pre-determined blocks (like what's happening here with dmi_data):

|       static void find_new_ec_fwstr(const struct dmi_header *dm, void *private)
|       {
|        char *ec_fw_string = (char *) private;
|        const char *dmi_data = (const char *)dm;
|        /*
|         * ThinkPad Embedded Controller Program Table on newer models
|         *
|         * Offset |  Name                | Width  | Description
|         * ----------------------------------------------------
|         *  0x00  | Type                 | BYTE   | 0x8C
|         *  0x01  | Length               | BYTE   |
|         *  0x02  | Handle               | WORD   | Varies
|         *  0x04  | Signature            | BYTEx6 | ASCII for "LENOVO"
|         *  0x0A  | OEM struct offset    | BYTE   | 0x0B
|         *  0x0B  | OEM struct number    | BYTE   | 0x07, for this structure
|         *  0x0C  | OEM struct revision  | BYTE   | 0x01, for this format
|         *  0x0D  | ECP version ID       | STR ID |
|         *  0x0E  | ECP release date     | STR ID |
|         */
|
|        /* Return if data structure not match */
|        if (dm->type != 140 || dm->length < 0x0F ||
|        memcmp(dmi_data + 4, "LENOVO", 6) != 0 ||
|        dmi_data[0x0A] != 0x0B || dmi_data[0x0B] != 0x07 ||
|        dmi_data[0x0C] != 0x01)
|        return;
|
|        /* fwstr is the first 8byte string  */
|        strncpy(ec_fw_string, dmi_data + 0x0F, 8);

... we shouldn't be using a C string api. Let's instead use memcpy() as
this more properly relays the intended behavior.

Do note that ec_fw_string will still end up being NUL-terminated since
we are memcpy'ing only 8 bytes into a buffer full of 18 zeroes. There's
still some trailing NUL-bytes there. To ensure this behavior, let's add
a BUILD_BUG_ON checking the length leaves space for at least one
trailing NUL-byte.

Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings
Link: https://github.com/KSPP/linux/issues/90
Cc: Kees Cook <keescook@chromium.org>
Signed-off-by: Justin Stitt <justinstitt@google.com>
Reviewed-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Reviewed-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20231020-strncpy-drivers-platform-x86-thinkpad_acpi-c-v1-1-312f2e33034f@google.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
drivers/platform/x86/thinkpad_acpi.c