scsi: target: Replace strlcpy() with strscpy()
authorAzeem Shaikh <azeemshaikh38@gmail.com>
Thu, 31 Aug 2023 14:36:38 +0000 (14:36 +0000)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 5 Sep 2023 09:55:20 +0000 (05:55 -0400)
strlcpy() reads the entire source buffer first.  This read may exceed the
destination size limit.  This is both inefficient and can lead to linear
read overflows if a source string is not NUL-terminated [1].  In an effort
to remove strlcpy() completely [2], replace strlcpy() here with strscpy().

Direct replacement is safe here since return value of -errno is used to
check for truncation instead of sizeof(dest).

[1] https://www.kernel.org/doc/html/latest/process/deprecated.html#strlcpy
[2] https://github.com/KSPP/linux/issues/89

Signed-off-by: Azeem Shaikh <azeemshaikh38@gmail.com>
Link: https://lore.kernel.org/r/20230831143638.232596-1-azeemshaikh38@gmail.com
Reviewed-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/target/target_core_configfs.c

index 936e5ff..d5860c1 100644 (file)
@@ -1392,16 +1392,16 @@ static ssize_t target_wwn_vendor_id_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_VENDOR_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_VENDOR_LEN) {
+       if (len < 0 || len > INQUIRY_VENDOR_LEN) {
                pr_err("Emulated T10 Vendor Identification exceeds"
                        " INQUIRY_VENDOR_LEN: " __stringify(INQUIRY_VENDOR_LEN)
                        "\n");
@@ -1448,16 +1448,16 @@ static ssize_t target_wwn_product_id_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_MODEL_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_MODEL_LEN) {
+       if (len < 0 || len > INQUIRY_MODEL_LEN) {
                pr_err("Emulated T10 Vendor exceeds INQUIRY_MODEL_LEN: "
                         __stringify(INQUIRY_MODEL_LEN)
                        "\n");
@@ -1504,16 +1504,16 @@ static ssize_t target_wwn_revision_store(struct config_item *item,
        /* +2 to allow for a trailing (stripped) '\n' and null-terminator */
        unsigned char buf[INQUIRY_REVISION_LEN + 2];
        char *stripped = NULL;
-       size_t len;
+       ssize_t len;
        ssize_t ret;
 
-       len = strlcpy(buf, page, sizeof(buf));
-       if (len < sizeof(buf)) {
+       len = strscpy(buf, page, sizeof(buf));
+       if (len > 0) {
                /* Strip any newline added from userspace. */
                stripped = strstrip(buf);
                len = strlen(stripped);
        }
-       if (len > INQUIRY_REVISION_LEN) {
+       if (len < 0 || len > INQUIRY_REVISION_LEN) {
                pr_err("Emulated T10 Revision exceeds INQUIRY_REVISION_LEN: "
                         __stringify(INQUIRY_REVISION_LEN)
                        "\n");