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

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.orgSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d32dcb06
...@@ -16,34 +16,34 @@ static inline const char *cdns2_decode_usb_irq(char *str, size_t size, ...@@ -16,34 +16,34 @@ static inline const char *cdns2_decode_usb_irq(char *str, size_t size,
{ {
int ret; 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) if (usb_irq & USBIRQ_SOF)
ret += snprintf(str + ret, size - ret, "SOF "); ret += scnprintf(str + ret, size - ret, "SOF ");
if (usb_irq & USBIRQ_SUTOK) if (usb_irq & USBIRQ_SUTOK)
ret += snprintf(str + ret, size - ret, "SUTOK "); ret += scnprintf(str + ret, size - ret, "SUTOK ");
if (usb_irq & USBIRQ_SUDAV) if (usb_irq & USBIRQ_SUDAV)
ret += snprintf(str + ret, size - ret, "SETUP "); ret += scnprintf(str + ret, size - ret, "SETUP ");
if (usb_irq & USBIRQ_SUSPEND) if (usb_irq & USBIRQ_SUSPEND)
ret += snprintf(str + ret, size - ret, "Suspend "); ret += scnprintf(str + ret, size - ret, "Suspend ");
if (usb_irq & USBIRQ_URESET) if (usb_irq & USBIRQ_URESET)
ret += snprintf(str + ret, size - ret, "Reset "); ret += scnprintf(str + ret, size - ret, "Reset ");
if (usb_irq & USBIRQ_HSPEED) if (usb_irq & USBIRQ_HSPEED)
ret += snprintf(str + ret, size - ret, "HS "); ret += scnprintf(str + ret, size - ret, "HS ");
if (usb_irq & USBIRQ_LPM) 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) 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) 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) 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) if (ret == size - 1)
pr_info("CDNS2: buffer overflowed.\n"); pr_info("CDNS2: buffer may be truncated.\n");
return str; return str;
} }
...@@ -54,28 +54,28 @@ static inline const char *cdns2_decode_dma_irq(char *str, size_t size, ...@@ -54,28 +54,28 @@ static inline const char *cdns2_decode_dma_irq(char *str, size_t size,
{ {
int ret; int ret;
ret = snprintf(str, size, "ISTS: %08x, %s: %08x ", ret = scnprintf(str, size, "ISTS: %08x, %s: %08x ",
ep_ists, ep_name, ep_sts); ep_ists, ep_name, ep_sts);
if (ep_sts & DMA_EP_STS_IOC) 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) 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) 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) 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) 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) 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) 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)) if (DMA_EP_STS_CCS(ep_sts))
ret += snprintf(str + ret, size - ret, "CCS "); ret += scnprintf(str + ret, size - ret, "CCS ");
if (ret >= size) if (ret == size - 1)
pr_info("CDNS2: buffer overflowed.\n"); pr_info("CDNS2: buffer may be truncated.\n");
return str; return str;
} }
...@@ -105,43 +105,43 @@ static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep, ...@@ -105,43 +105,43 @@ static inline const char *cdns2_raw_ring(struct cdns2_endpoint *pep,
int ret; int ret;
int i; 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]; trb = &trbs[ring->dequeue];
dma = cdns2_trb_virt_to_dma(pep, trb); 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", "\n\t\tRing deq index: %d, trb: V=%p, P=0x%pad\n",
ring->dequeue, trb, &dma); ring->dequeue, trb, &dma);
trb = &trbs[ring->enqueue]; trb = &trbs[ring->enqueue];
dma = cdns2_trb_virt_to_dma(pep, trb); 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", "\t\tRing enq index: %d, trb: V=%p, P=0x%pad\n",
ring->enqueue, trb, &dma); 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", "\t\tfree trbs: %d, CCS=%d, PCS=%d\n",
ring->free_trbs, ring->ccs, ring->pcs); ring->free_trbs, ring->ccs, ring->pcs);
if (TRBS_PER_SEGMENT > 40) { 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); "\t\tTransfer ring %d too big\n", TRBS_PER_SEGMENT);
return str; return str;
} }
dma = ring->dma; dma = ring->dma;
for (i = 0; i < TRBS_PER_SEGMENT; ++i) { for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &trbs[i]; trb = &trbs[i];
ret += snprintf(str + ret, size - ret, ret += scnprintf(str + ret, size - ret,
"\t\t@%pad %08x %08x %08x\n", &dma, "\t\t@%pad %08x %08x %08x\n", &dma,
le32_to_cpu(trb->buffer), le32_to_cpu(trb->buffer),
le32_to_cpu(trb->length), le32_to_cpu(trb->length),
le32_to_cpu(trb->control)); le32_to_cpu(trb->control));
dma += sizeof(*trb); dma += sizeof(*trb);
} }
if (ret >= size) if (ret == size - 1)
pr_info("CDNS2: buffer overflowed.\n"); pr_info("CDNS2: buffer may be truncated.\n");
return str; return str;
} }
...@@ -166,36 +166,36 @@ static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags, ...@@ -166,36 +166,36 @@ static inline const char *cdns2_decode_trb(char *str, size_t size, u32 flags,
switch (type) { switch (type) {
case TRB_LINK: case TRB_LINK:
ret = snprintf(str, size, ret = scnprintf(str, size,
"LINK %08x type '%s' flags %c:%c:%c%c:%c", "LINK %08x type '%s' flags %c:%c:%c%c:%c",
buffer, cdns2_trb_type_string(type), buffer, cdns2_trb_type_string(type),
flags & TRB_CYCLE ? 'C' : 'c', flags & TRB_CYCLE ? 'C' : 'c',
flags & TRB_TOGGLE ? 'T' : 't', flags & TRB_TOGGLE ? 'T' : 't',
flags & TRB_CHAIN ? 'C' : 'c', flags & TRB_CHAIN ? 'C' : 'c',
flags & TRB_CHAIN ? 'H' : 'h', flags & TRB_CHAIN ? 'H' : 'h',
flags & TRB_IOC ? 'I' : 'i'); flags & TRB_IOC ? 'I' : 'i');
break; break;
case TRB_NORMAL: case TRB_NORMAL:
ret = snprintf(str, size, ret = scnprintf(str, size,
"type: '%s', Buffer: %08x, length: %ld, burst len: %ld, " "type: '%s', Buffer: %08x, length: %ld, burst len: %ld, "
"flags %c:%c:%c%c:%c", "flags %c:%c:%c%c:%c",
cdns2_trb_type_string(type), cdns2_trb_type_string(type),
buffer, TRB_LEN(length), buffer, TRB_LEN(length),
TRB_FIELD_TO_BURST(length), TRB_FIELD_TO_BURST(length),
flags & TRB_CYCLE ? 'C' : 'c', flags & TRB_CYCLE ? 'C' : 'c',
flags & TRB_ISP ? 'I' : 'i', flags & TRB_ISP ? 'I' : 'i',
flags & TRB_CHAIN ? 'C' : 'c', flags & TRB_CHAIN ? 'C' : 'c',
flags & TRB_CHAIN ? 'H' : 'h', flags & TRB_CHAIN ? 'H' : 'h',
flags & TRB_IOC ? 'I' : 'i'); flags & TRB_IOC ? 'I' : 'i');
break; break;
default: 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), cdns2_trb_type_string(type),
buffer, length, flags); buffer, length, flags);
} }
if (ret >= size) if (ret == size - 1)
pr_info("CDNS2: buffer overflowed.\n"); pr_info("CDNS2: buffer may be truncated.\n");
return str; return str;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment