Commit 01dc7f7c authored by Lee Jones's avatar Lee Jones Committed by Greg Kroah-Hartman
Browse files

usb: cdns2: Replace snprintf() with the safer scnprintf() variant

There is a general misunderstanding amongst engineers that {v}snprintf()
returns the length of the data *actually* encoded into the destination
array.  However, as per the C99 standard {v}snprintf() really returns
the length of the data that *would have been* written if there were
enough space for it.  This misunderstanding has led to buffer-overruns
in the past.  It's generally considered safer to use the {v}scnprintf()
variants in their place (or even sprintf() in simple cases).  So let's
do that.

Link: https://lwn.net/Articles/69419/
Link: https://github.com/KSPP/linux/issues/105


Cc: Pawel Laszczak <pawell@cadence.com>
Signed-off-by: default avatarLee Jones <lee@kernel.org>
Link: https://lore.kernel.org/r/20231213164246.1021885-7-lee@kernel.org


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d32dcb06
Loading
Loading
Loading
Loading
+69 −69
Original line number Diff line number Diff line
@@ -16,34 +16,34 @@ static inline const char *cdns2_decode_usb_irq(char *str, size_t size,
{
	int ret;

	ret = snprintf(str, size, "usbirq: 0x%02x - ", usb_irq);
	ret = scnprintf(str, size, "usbirq: 0x%02x - ", usb_irq);

	if (usb_irq & USBIRQ_SOF)
		ret += snprintf(str + ret, size - ret, "SOF ");
		ret += scnprintf(str + ret, size - ret, "SOF ");
	if (usb_irq & USBIRQ_SUTOK)
		ret += snprintf(str + ret, size - ret, "SUTOK ");
		ret += scnprintf(str + ret, size - ret, "SUTOK ");
	if (usb_irq & USBIRQ_SUDAV)
		ret += snprintf(str + ret, size - ret, "SETUP ");
		ret += scnprintf(str + ret, size - ret, "SETUP ");
	if (usb_irq & USBIRQ_SUSPEND)
		ret += snprintf(str + ret, size - ret, "Suspend ");
		ret += scnprintf(str + ret, size - ret, "Suspend ");
	if (usb_irq & USBIRQ_URESET)
		ret += snprintf(str + ret, size - ret, "Reset ");
		ret += scnprintf(str + ret, size - ret, "Reset ");
	if (usb_irq & USBIRQ_HSPEED)
		ret += snprintf(str + ret, size - ret, "HS ");
		ret += scnprintf(str + ret, size - ret, "HS ");
	if (usb_irq & USBIRQ_LPM)
		ret += snprintf(str + ret, size - ret, "LPM ");
		ret += scnprintf(str + ret, size - ret, "LPM ");

	ret += snprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);
	ret += scnprintf(str + ret, size - ret, ", EXT: 0x%02x - ", ext_irq);

	if (ext_irq & EXTIRQ_WAKEUP)
		ret += snprintf(str + ret, size - ret, "Wakeup ");
		ret += scnprintf(str + ret, size - ret, "Wakeup ");
	if (ext_irq & EXTIRQ_VBUSFAULT_FALL)
		ret += snprintf(str + ret, size - ret, "VBUS_FALL ");
		ret += scnprintf(str + ret, size - ret, "VBUS_FALL ");
	if (ext_irq & EXTIRQ_VBUSFAULT_RISE)
		ret += snprintf(str + ret, size - ret, "VBUS_RISE ");
		ret += scnprintf(str + ret, size - ret, "VBUS_RISE ");

	if (ret >= size)
		pr_info("CDNS2: buffer overflowed.\n");
	if (ret == size - 1)
		pr_info("CDNS2: buffer may be truncated.\n");

	return str;
}
@@ -54,28 +54,28 @@ static inline const char *cdns2_decode_dma_irq(char *str, size_t size,
{
	int ret;

	ret = snprintf(str, size, "ISTS: %08x, %s: %08x ",
	ret = scnprintf(str, size, "ISTS: %08x, %s: %08x ",
			ep_ists, ep_name, ep_sts);

	if (ep_sts & DMA_EP_STS_IOC)
		ret += snprintf(str + ret, size - ret, "IOC ");
		ret += scnprintf(str + ret, size - ret, "IOC ");
	if (ep_sts & DMA_EP_STS_ISP)
		ret += snprintf(str + ret, size - ret, "ISP ");
		ret += scnprintf(str + ret, size - ret, "ISP ");
	if (ep_sts & DMA_EP_STS_DESCMIS)
		ret += snprintf(str + ret, size - ret, "DESCMIS ");
		ret += scnprintf(str + ret, size - ret, "DESCMIS ");
	if (ep_sts & DMA_EP_STS_TRBERR)
		ret += snprintf(str + ret, size - ret, "TRBERR ");
		ret += scnprintf(str + ret, size - ret, "TRBERR ");
	if (ep_sts & DMA_EP_STS_OUTSMM)
		ret += snprintf(str + ret, size - ret, "OUTSMM ");
		ret += scnprintf(str + ret, size - ret, "OUTSMM ");
	if (ep_sts & DMA_EP_STS_ISOERR)
		ret += snprintf(str + ret, size - ret, "ISOERR ");
		ret += scnprintf(str + ret, size - ret, "ISOERR ");
	if (ep_sts & DMA_EP_STS_DBUSY)
		ret += snprintf(str + ret, size - ret, "DBUSY ");
		ret += scnprintf(str + ret, size - ret, "DBUSY ");
	if (DMA_EP_STS_CCS(ep_sts))
		ret += snprintf(str + ret, size - ret, "CCS ");
		ret += scnprintf(str + ret, size - ret, "CCS ");

	if (ret >= size)
		pr_info("CDNS2: buffer overflowed.\n");
	if (ret == size - 1)
		pr_info("CDNS2: buffer may be truncated.\n");

	return str;
}
@@ -105,26 +105,26 @@ static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
	int ret;
	int i;

	ret = snprintf(str, size, "\n\t\tTR for %s:", pep->name);
	ret = scnprintf(str, size, "\n\t\tTR for %s:", pep->name);

	trb = &trbs[ring->dequeue];
	dma = cdns2_trb_virt_to_dma(pep, trb);
	ret += snprintf(str + ret, size - ret,
	ret += scnprintf(str + ret, size - ret,
			 "\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
			 ring->dequeue, trb, &dma);

	trb = &trbs[ring->enqueue];
	dma = cdns2_trb_virt_to_dma(pep, trb);
	ret += snprintf(str + ret, size - ret,
	ret += scnprintf(str + ret, size - ret,
			 "\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
			 ring->enqueue, trb, &dma);

	ret += snprintf(str + ret, size - ret,
	ret += scnprintf(str + ret, size - ret,
			 "\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
			 ring->free_trbs, ring->ccs, ring->pcs);

	if (TRBS_PER_SEGMENT > 40) {
		ret += snprintf(str + ret, size - ret,
		ret += scnprintf(str + ret, size - ret,
				 "\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
		return str;
	}
@@ -132,7 +132,7 @@ static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
	dma = ring->dma;
	for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
		trb = &trbs[i];
		ret += snprintf(str + ret, size - ret,
		ret += scnprintf(str + ret, size - ret,
				 "\t\t@%pad %08x %08x %08x\n", &dma,
				 le32_to_cpu(trb->buffer),
				 le32_to_cpu(trb->length),
@@ -140,8 +140,8 @@ static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
		dma += sizeof(*trb);
	}

	if (ret >= size)
		pr_info("CDNS2: buffer overflowed.\n");
	if (ret == size - 1)
		pr_info("CDNS2: buffer may be truncated.\n");

	return str;
}
@@ -166,7 +166,7 @@ static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,

	switch (type) {
	case TRB_LINK:
		ret = snprintf(str, size,
		ret = scnprintf(str, size,
				"LINK %08x type '%s' flags %c:%c:%c%c:%c",
				buffer, cdns2_trb_type_string(type),
				flags & TRB_CYCLE ? 'C' : 'c',
@@ -176,7 +176,7 @@ static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
				flags & TRB_IOC ? 'I' : 'i');
		break;
	case TRB_NORMAL:
		ret = snprintf(str, size,
		ret = scnprintf(str, size,
				"type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
				"flags %c:%c:%c%c:%c",
				cdns2_trb_type_string(type),
@@ -189,13 +189,13 @@ static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
				flags & TRB_IOC ? 'I' : 'i');
		break;
	default:
		ret = snprintf(str, size, "type '%s' -> raw %08x %08x %08x",
		ret = scnprintf(str, size, "type '%s' -> raw %08x %08x %08x",
				cdns2_trb_type_string(type),
				buffer, length, flags);
	}

	if (ret >= size)
		pr_info("CDNS2: buffer overflowed.\n");
	if (ret == size - 1)
		pr_info("CDNS2: buffer may be truncated.\n");

	return str;
}