[PATCH] scsi: bfa: Replace strlcat() with scnprintf()

Ian Bridges <[email protected]> Tue, 4 Aug 2026 23:25:24 -0500
Newsgroups gmane.linux.scsi,gmane.linux.kernel
Message-ID <anK7NApeyv03uqXD@dev>
In preparation for removing the strlcat() API[1], replace its uses
in the symbolic name builders. Each affected function assembles a
fixed sequence of string fragments into one buffer. A single
scnprintf() per function writes the same bytes, including on
truncation, and states the buffer size once instead of once per
append.

Link: https://github.com/KSPP/linux/issues/370 [1]
Signed-off-by: Ian Bridges <[email protected]>
---
The destination buffers are byte identical to the old code in all
cases, including truncation of oversized fragments and the bytes
past the terminator.

In bfa_fcs_fabric_psymb_init() the patch level if/else disappears
into the format arguments. Both branches append the same OS name
and separator, and printing an empty patch string appends nothing.

The patch was tested as follows.

- A differential harness compiled the old and new composition
  sequences side by side, with struct layouts mirroring the driver
  so unterminated fields overrun into the same neighbor bytes on both sides.
  Directed sweeps over every fragment length, including
  unterminated full arrays, plus 50000 randomized rounds. 257862
  cases, byte identical output in all of them.
- A KUnit oracle suite called the real fabric name builders in a
  QEMU kernel with KASAN, UBSAN and FORTIFY_SOURCE enabled, on the
  base and on the patched branch, against expected byte tables
  generated by the harness. Both runs matched the tables in all
  twelve cases, and the old and new tables are identical, so the
  kernel builds of the old and new code produce the same arrays.
- W=1 builds of the two changed objects on x86 and arm64, zero new
  warnings.
- A QEMU module load and unload smoke test of the patched bfa.ko
  passed. No hardware was available to test on, so runtime coverage
  comes from the KUnit oracle rather than device testing.

 drivers/scsi/bfa/bfa_fcs.c       | 81 +++++++-------------------------
 drivers/scsi/bfa/bfa_fcs_lport.c | 36 +++++---------
 2 files changed, 29 insertions(+), 88 deletions(-)

diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c
index 9b57312f43f5..8bf0d0c6b38f 100644
--- a/drivers/scsi/bfa/bfa_fcs.c
+++ b/drivers/scsi/bfa/bfa_fcs.c
@@ -760,50 +760,15 @@ bfa_fcs_fabric_psymb_init(struct bfa_fcs_fabric_s *fabric)
 
 	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
 
-	/* Model name/number */
-	strscpy(port_cfg->sym_name.symname, model,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		BFA_SYMNAME_MAXLEN);
-
-	/* Driver Version */
-	strlcat(port_cfg->sym_name.symname, driver_info->version,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		BFA_SYMNAME_MAXLEN);
-
-	/* Host machine name */
-	strlcat(port_cfg->sym_name.symname,
-		driver_info->host_machine_name,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->sym_name.symname, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-		BFA_SYMNAME_MAXLEN);
-
-	/*
-	 * Host OS Info :
-	 * If OS Patch Info is not there, do not truncate any bytes from the
-	 * OS name string and instead copy the entire OS info string (64 bytes).
-	 */
-	if (driver_info->host_os_patch[0] == '\0') {
-		strlcat(port_cfg->sym_name.symname,
-			driver_info->host_os_name,
-			BFA_SYMNAME_MAXLEN);
-		strlcat(port_cfg->sym_name.symname,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			BFA_SYMNAME_MAXLEN);
-	} else {
-		strlcat(port_cfg->sym_name.symname,
-			driver_info->host_os_name,
-			BFA_SYMNAME_MAXLEN);
-		strlcat(port_cfg->sym_name.symname,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			BFA_SYMNAME_MAXLEN);
-
-		/* Append host OS Patch Info */
-		strlcat(port_cfg->sym_name.symname,
-			driver_info->host_os_patch,
-			BFA_SYMNAME_MAXLEN);
-	}
+	/* Model | Driver Version | Host machine name | Host OS | OS patch */
+	scnprintf(port_cfg->sym_name.symname, BFA_SYMNAME_MAXLEN,
+		  "%s%s%s%s%s%s%s%s%s",
+		  model, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->version, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->host_machine_name,
+		  BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->host_os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->host_os_patch);
 
 	/* null terminate */
 	port_cfg->sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
@@ -821,27 +786,13 @@ bfa_fcs_fabric_nsymb_init(struct bfa_fcs_fabric_s *fabric)
 
 	bfa_ioc_get_adapter_model(&fabric->fcs->bfa->ioc, model);
 
-	/* Model name/number */
-	strscpy(port_cfg->node_sym_name.symname, model,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->node_sym_name.symname,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			BFA_SYMNAME_MAXLEN);
-
-	/* Driver Version */
-	strlcat(port_cfg->node_sym_name.symname, (char *)driver_info->version,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->node_sym_name.symname,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			BFA_SYMNAME_MAXLEN);
-
-	/* Host machine name */
-	strlcat(port_cfg->node_sym_name.symname,
-		driver_info->host_machine_name,
-		BFA_SYMNAME_MAXLEN);
-	strlcat(port_cfg->node_sym_name.symname,
-			BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			BFA_SYMNAME_MAXLEN);
+	/* Model | Driver Version | Host machine name */
+	scnprintf(port_cfg->node_sym_name.symname, BFA_SYMNAME_MAXLEN,
+		  "%s%s%s%s%s%s",
+		  model, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->version, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
+		  driver_info->host_machine_name,
+		  BFA_FCS_PORT_SYMBNAME_SEPARATOR);
 
 	/* null terminate */
 	port_cfg->node_sym_name.symname[BFA_SYMNAME_MAXLEN - 1] = 0;
diff --git a/drivers/scsi/bfa/bfa_fcs_lport.c b/drivers/scsi/bfa/bfa_fcs_lport.c
index 2df399c537c1..9ac761272132 100644
--- a/drivers/scsi/bfa/bfa_fcs_lport.c
+++ b/drivers/scsi/bfa/bfa_fcs_lport.c
@@ -2599,19 +2599,15 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
 	strscpy(hba_attr->driver_version, (char *)driver_info->version,
 		sizeof(hba_attr->driver_version));
 
-	strscpy(hba_attr->os_name, driver_info->host_os_name,
-		sizeof(hba_attr->os_name));
-
 	/*
 	 * If there is a patch level, append it
 	 * to the os name along with a separator
 	 */
-	if (driver_info->host_os_patch[0] != '\0') {
-		strlcat(hba_attr->os_name, BFA_FCS_PORT_SYMBNAME_SEPARATOR,
-			sizeof(hba_attr->os_name));
-		strlcat(hba_attr->os_name, driver_info->host_os_patch,
-				sizeof(hba_attr->os_name));
-	}
+	scnprintf(hba_attr->os_name, sizeof(hba_attr->os_name), "%s%s%s",
+		  driver_info->host_os_name,
+		  driver_info->host_os_patch[0] != '\0' ?
+			BFA_FCS_PORT_SYMBNAME_SEPARATOR : "",
+		  driver_info->host_os_patch);
 
 	/* Retrieve the max frame size from the port attr */
 	bfa_fcs_fdmi_get_portattr(fdmi, &fcs_port_attr);
@@ -4589,13 +4585,10 @@ bfa_fcs_lport_ns_send_rspn_id(void *ns_cbarg, struct bfa_fcxp_s *fcxp_alloced)
 		 * to that of the base port.
 		 */
 
-		strscpy(symbl,
-			(char *)&(bfa_fcs_lport_get_psym_name
-			 (bfa_fcs_get_base_port(port->fcs))),
-			sizeof(symbl));
-
-		strlcat(symbl, (char *)&(bfa_fcs_lport_get_psym_name(port)),
-			sizeof(symbl));
+		scnprintf(symbl, sizeof(symbl), "%s%s",
+			  (char *)&(bfa_fcs_lport_get_psym_name
+			   (bfa_fcs_get_base_port(port->fcs))),
+			  (char *)&(bfa_fcs_lport_get_psym_name(port)));
 	} else {
 		psymbl = (u8 *) &(bfa_fcs_lport_get_psym_name(port));
 	}
@@ -5116,13 +5109,10 @@ bfa_fcs_lport_ns_util_send_rspn_id(void *cbarg, struct bfa_fcxp_s *fcxp_alloced)
 		 * For Vports, we append the vport's port symbolic name
 		 * to that of the base port.
 		 */
-		strscpy(symbl, (char *)&(bfa_fcs_lport_get_psym_name
-			(bfa_fcs_get_base_port(port->fcs))),
-			sizeof(symbl));
-
-		strlcat(symbl,
-			(char *)&(bfa_fcs_lport_get_psym_name(port)),
-			sizeof(symbl));
+		scnprintf(symbl, sizeof(symbl), "%s%s",
+			  (char *)&(bfa_fcs_lport_get_psym_name
+			   (bfa_fcs_get_base_port(port->fcs))),
+			  (char *)&(bfa_fcs_lport_get_psym_name(port)));
 	}
 
 	len = fc_rspnid_build(&fchs, bfa_fcxp_get_reqbuf(fcxp),
-- 
2.47.3