Linux SCSI subsystem development
 help / color / mirror / Atom feed
From: Ian Bridges <icb@fastmail.org>
To: Anil Gurumurthy <anil.gurumurthy@qlogic.com>,
	Sudarsana Kalluru <sudarsana.kalluru@qlogic.com>,
	"James E.J. Bottomley" <James.Bottomley@hansenpartnership.com>,
	"Martin K. Petersen" <martin.petersen@oracle.com>
Cc: linux-scsi@vger.kernel.org, linux-kernel@vger.kernel.org,
	linux-hardening@vger.kernel.org
Subject: [PATCH] scsi: bfa: Replace strlcat() with scnprintf()
Date: Tue, 4 Aug 2026 23:25:24 -0500	[thread overview]
Message-ID: <anK7NApeyv03uqXD@dev> (raw)

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 <icb@fastmail.org>
---
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


                 reply	other threads:[~2026-08-05  4:25 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=anK7NApeyv03uqXD@dev \
    --to=icb@fastmail.org \
    --cc=James.Bottomley@hansenpartnership.com \
    --cc=anil.gurumurthy@qlogic.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=sudarsana.kalluru@qlogic.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox