In preparation for removing the strlcat() API[1], replace its uses in
lpfc_info().

The function accumulates a variable number of optional fragments,
which is what seq_buf is for. The intermediate tmp buffer and the
per fragment overflow checks become unnecessary. seq_buf is memory
safe by construction and silently truncates in the same way as the
replaced pattern.

The old code passed phba->ModelDesc as the format string of the first
scnprintf() call. The model description comes from adapter VPD data.
seq_buf_printf() takes a format string, so the replacement prints it
through "%s". A model description containing conversion specifiers is
no longer interpreted.

Link: https://github.com/KSPP/linux/issues/370 [1]
Signed-off-by: Ian Bridges <[email protected]>
---
A model description that contains percent characters is now emitted
literally. The old code interpreted it as a format string, which is
undefined behavior for any conversion that consumes an argument. The
differential harness confirmed byte identical output for 200000
randomized percent-free model strings across all fragment
combinations, and demonstrated the old interpretation with a directed
"%%" input. The KUnit corpus confirmed the same as compiled kernel
code.

Once the seq_buf overflows, later appends write nothing, so removing
the early exits does not change the produced bytes. The harness
confirmed identical output over the full field ranges.

 drivers/scsi/lpfc/lpfc_scsi.c | 49 +++++++++++------------------------
 1 file changed, 15 insertions(+), 34 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index f2cab134af7f..8a795c65e3c3 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -21,6 +21,7 @@
  * included with this package.                                     *
  *******************************************************************/
 #include <linux/pci.h>
+#include <linux/seq_buf.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/export.h>
@@ -5103,57 +5104,37 @@ lpfc_info(struct Scsi_Host *host)
        struct lpfc_hba   *phba = vport->phba;
        int link_speed = 0;
        static char lpfcinfobuf[384];
-       char tmp[384] = {0};
+       struct seq_buf s;
 
        memset(lpfcinfobuf, 0, sizeof(lpfcinfobuf));
+       seq_buf_init(&s, lpfcinfobuf, sizeof(lpfcinfobuf));
        if (phba && phba->pcidev){
                /* Model Description */
-               scnprintf(tmp, sizeof(tmp), phba->ModelDesc);
-               if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
-                   sizeof(lpfcinfobuf))
-                       goto buffer_done;
+               seq_buf_printf(&s, "%s", phba->ModelDesc);
 
                /* PCI Info */
-               scnprintf(tmp, sizeof(tmp),
-                         " on PCI bus %02x device %02x irq %d",
-                         phba->pcidev->bus->number, phba->pcidev->devfn,
-                         phba->pcidev->irq);
-               if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
-                   sizeof(lpfcinfobuf))
-                       goto buffer_done;
+               seq_buf_printf(&s, " on PCI bus %02x device %02x irq %d",
+                              phba->pcidev->bus->number, phba->pcidev->devfn,
+                              phba->pcidev->irq);
 
                /* Port Number */
-               if (phba->Port[0]) {
-                       scnprintf(tmp, sizeof(tmp), " port %s", phba->Port);
-                       if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
-                           sizeof(lpfcinfobuf))
-                               goto buffer_done;
-               }
+               if (phba->Port[0])
+                       seq_buf_printf(&s, " port %s", phba->Port);
 
                /* Link Speed */
                link_speed = lpfc_sli_port_speed_get(phba);
-               if (link_speed != 0) {
-                       scnprintf(tmp, sizeof(tmp),
-                                 " Logical Link Speed: %d Mbps", link_speed);
-                       if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
-                           sizeof(lpfcinfobuf))
-                               goto buffer_done;
-               }
+               if (link_speed != 0)
+                       seq_buf_printf(&s, " Logical Link Speed: %d Mbps",
+                                      link_speed);
 
                /* Support for BSG ioctls */
-               scnprintf(tmp, sizeof(tmp), " BSG");
-               if (strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf)) >=
-                   sizeof(lpfcinfobuf))
-                       goto buffer_done;
+               seq_buf_printf(&s, " BSG");
 
                /* PCI resettable */
-               if (!lpfc_check_pci_resettable(phba)) {
-                       scnprintf(tmp, sizeof(tmp), " PCI resettable");
-                       strlcat(lpfcinfobuf, tmp, sizeof(lpfcinfobuf));
-               }
+               if (!lpfc_check_pci_resettable(phba))
+                       seq_buf_printf(&s, " PCI resettable");
        }
 
-buffer_done:
        return lpfcinfobuf;
 }
 
-- 
2.47.3


Reply via email to