[PATCH] scsi: 3w-sas: bound firmware error string parsing
From: Pengpeng Hou
Date: Fri Jul 03 2026 - 21:06:38 EST
3w-sas parses two NUL-separated firmware strings from the fixed
err_specific_desc[] field. The AEN and sense paths locate the second
string with strlen(first) + 1 before guaranteeing that the first
string is terminated inside the array.
Force a terminator in the fixed field before parsing, use strnlen()
for the first and optional second strings, and copy only the bytes
known to reside in err_specific_desc[].
Signed-off-by: Pengpeng Hou <pengpeng@xxxxxxxxxxx>
---
drivers/scsi/3w-sas.c | 28 +++++++++++++++++++++++-----
1 file changed, 23 insertions(+), 5 deletions(-)
--- a/drivers/scsi/3w-sas.c
+++ b/drivers/scsi/3w-sas.c
@@ -227,6 +227,7 @@
unsigned short aen;
char host[16];
char *error_str;
+ size_t desc_len, error_len;
tw_dev->aen_count++;
@@ -250,11 +251,21 @@
tw_dev->error_sequence_id++;
/* Check for embedded error string */
- error_str = &(header->err_specific_desc[strlen(header->err_specific_desc)+1]);
-
header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
- event->parameter_len = strlen(header->err_specific_desc);
- memcpy(event->parameter_data, header->err_specific_desc, event->parameter_len + 1 + strlen(error_str));
+ desc_len = strnlen(header->err_specific_desc,
+ sizeof(header->err_specific_desc));
+ error_str = "";
+ error_len = 0;
+ if (desc_len + 1 < sizeof(header->err_specific_desc)) {
+ error_str = &header->err_specific_desc[desc_len + 1];
+ error_len = strnlen(error_str,
+ sizeof(header->err_specific_desc) -
+ desc_len - 1);
+ }
+
+ event->parameter_len = desc_len;
+ memcpy(event->parameter_data, header->err_specific_desc,
+ desc_len + (error_len ? 1 + error_len : 0));
if (event->severity != TW_AEN_SEVERITY_DEBUG)
printk(KERN_WARNING "3w-sas:%s AEN: %s (0x%02X:0x%04X): %s:%s.\n",
host,
@@ -862,12 +873,19 @@
TW_Command_Full *full_command_packet;
unsigned short error;
char *error_str;
+ size_t desc_len;
header = tw_dev->sense_buffer_virt[i];
full_command_packet = tw_dev->command_packet_virt[request_id];
/* Get embedded firmware error string */
- error_str = &(header->err_specific_desc[strlen(header->err_specific_desc) + 1]);
+ header->err_specific_desc[sizeof(header->err_specific_desc) - 1] = '\0';
+ desc_len = strnlen(header->err_specific_desc,
+ sizeof(header->err_specific_desc));
+ if (desc_len + 1 < sizeof(header->err_specific_desc))
+ error_str = &header->err_specific_desc[desc_len + 1];
+ else
+ error_str = "";
/* Don't print error for Logical unit not supported during rollcall */
error = le16_to_cpu(header->status_block.error);