xhci: fix unsafe memory usage in xhci tracing
authorMathias Nyman <mathias.nyman@linux.intel.com>
Fri, 20 Aug 2021 12:34:58 +0000 (15:34 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 26 Aug 2021 11:06:02 +0000 (13:06 +0200)
Removes static char buffer usage in the following decode functions:
xhci_decode_trb()
xhci_decode_ptortsc()

Caller must provide a buffer to use.
In tracing use __get_str() as recommended to pass buffer.

Minor chanes are needed in xhci debugfs code as these functions are also
used there. Changes include moving XHCI_MSG_MAX definititon from
xhci-trace.h to xhci.h

Cc: <stable@vger.kernel.org>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20210820123503.2605901-2-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-debugfs.c
drivers/usb/host/xhci-trace.h
drivers/usb/host/xhci.h

index 2c0fda5..85c12f5 100644 (file)
@@ -198,12 +198,13 @@ static void xhci_ring_dump_segment(struct seq_file *s,
        int                     i;
        dma_addr_t              dma;
        union xhci_trb          *trb;
+       char                    str[XHCI_MSG_MAX];
 
        for (i = 0; i < TRBS_PER_SEGMENT; i++) {
                trb = &seg->trbs[i];
                dma = seg->dma + i * sizeof(*trb);
                seq_printf(s, "%pad: %s\n", &dma,
-                          xhci_decode_trb(le32_to_cpu(trb->generic.field[0]),
+                          xhci_decode_trb(str, XHCI_MSG_MAX, le32_to_cpu(trb->generic.field[0]),
                                           le32_to_cpu(trb->generic.field[1]),
                                           le32_to_cpu(trb->generic.field[2]),
                                           le32_to_cpu(trb->generic.field[3])));
@@ -341,9 +342,10 @@ static int xhci_portsc_show(struct seq_file *s, void *unused)
 {
        struct xhci_port        *port = s->private;
        u32                     portsc;
+       char                    str[XHCI_MSG_MAX];
 
        portsc = readl(port->addr);
-       seq_printf(s, "%s\n", xhci_decode_portsc(portsc));
+       seq_printf(s, "%s\n", xhci_decode_portsc(str, portsc));
 
        return 0;
 }
index 627abd2..5e1c50c 100644 (file)
@@ -25,8 +25,6 @@
 #include "xhci.h"
 #include "xhci-dbgcap.h"
 
-#define XHCI_MSG_MAX   500
-
 DECLARE_EVENT_CLASS(xhci_log_msg,
        TP_PROTO(struct va_format *vaf),
        TP_ARGS(vaf),
@@ -122,6 +120,7 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
                __field(u32, field1)
                __field(u32, field2)
                __field(u32, field3)
+               __dynamic_array(char, str, XHCI_MSG_MAX)
        ),
        TP_fast_assign(
                __entry->type = ring->type;
@@ -131,7 +130,7 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
                __entry->field3 = le32_to_cpu(trb->field[3]);
        ),
        TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
-                       xhci_decode_trb(__entry->field0, __entry->field1,
+                 xhci_decode_trb(__get_str(str), XHCI_MSG_MAX, __entry->field0, __entry->field1,
                                        __entry->field2, __entry->field3)
        )
 );
@@ -523,6 +522,7 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
                    TP_STRUCT__entry(
                                     __field(u32, portnum)
                                     __field(u32, portsc)
+                                    __dynamic_array(char, str, XHCI_MSG_MAX)
                                     ),
                    TP_fast_assign(
                                   __entry->portnum = portnum;
@@ -530,7 +530,7 @@ DECLARE_EVENT_CLASS(xhci_log_portsc,
                                   ),
                    TP_printk("port-%d: %s",
                              __entry->portnum,
-                             xhci_decode_portsc(__entry->portsc)
+                             xhci_decode_portsc(__get_str(str), __entry->portsc)
                              )
 );
 
index 3c7d281..99ae999 100644 (file)
@@ -22,6 +22,9 @@
 #include       "xhci-ext-caps.h"
 #include "pci-quirks.h"
 
+/* max buffer size for trace and debug messages */
+#define XHCI_MSG_MAX           500
+
 /* xHCI PCI Configuration Registers */
 #define XHCI_SBRN_OFFSET       (0x60)
 
@@ -2235,15 +2238,14 @@ static inline char *xhci_slot_state_string(u32 state)
        }
 }
 
-static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
-               u32 field3)
+static inline const char *xhci_decode_trb(char *str, size_t size,
+                                         u32 field0, u32 field1, u32 field2, u32 field3)
 {
-       static char str[256];
        int type = TRB_FIELD_TO_TYPE(field3);
 
        switch (type) {
        case TRB_LINK:
-               sprintf(str,
+               snprintf(str, size,
                        "LINK %08x%08x intr %d type '%s' flags %c:%c:%c:%c",
                        field1, field0, GET_INTR_TARGET(field2),
                        xhci_trb_type_string(type),
@@ -2260,7 +2262,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
        case TRB_HC_EVENT:
        case TRB_DEV_NOTE:
        case TRB_MFINDEX_WRAP:
-               sprintf(str,
+               snprintf(str, size,
                        "TRB %08x%08x status '%s' len %d slot %d ep %d type '%s' flags %c:%c",
                        field1, field0,
                        xhci_trb_comp_code_string(GET_COMP_CODE(field2)),
@@ -2273,7 +2275,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
 
                break;
        case TRB_SETUP:
-               sprintf(str, "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c",
+               snprintf(str, size,
+                       "bRequestType %02x bRequest %02x wValue %02x%02x wIndex %02x%02x wLength %d length %d TD size %d intr %d type '%s' flags %c:%c:%c",
                                field0 & 0xff,
                                (field0 & 0xff00) >> 8,
                                (field0 & 0xff000000) >> 24,
@@ -2290,7 +2293,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                                field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_DATA:
-               sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c",
+               snprintf(str, size,
+                        "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c",
                                field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
                                GET_INTR_TARGET(field2),
                                xhci_trb_type_string(type),
@@ -2303,7 +2307,8 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                                field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_STATUS:
-               sprintf(str, "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c",
+               snprintf(str, size,
+                        "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c",
                                field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
                                GET_INTR_TARGET(field2),
                                xhci_trb_type_string(type),
@@ -2316,7 +2321,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
        case TRB_ISOC:
        case TRB_EVENT_DATA:
        case TRB_TR_NOOP:
-               sprintf(str,
+               snprintf(str, size,
                        "Buffer %08x%08x length %d TD size %d intr %d type '%s' flags %c:%c:%c:%c:%c:%c:%c:%c",
                        field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
                        GET_INTR_TARGET(field2),
@@ -2333,21 +2338,21 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
 
        case TRB_CMD_NOOP:
        case TRB_ENABLE_SLOT:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: flags %c",
                        xhci_trb_type_string(type),
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_DISABLE_SLOT:
        case TRB_NEG_BANDWIDTH:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: slot %d flags %c",
                        xhci_trb_type_string(type),
                        TRB_TO_SLOT_ID(field3),
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_ADDR_DEV:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: ctx %08x%08x slot %d flags %c:%c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2356,7 +2361,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_CONFIG_EP:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: ctx %08x%08x slot %d flags %c:%c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2365,7 +2370,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_EVAL_CONTEXT:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: ctx %08x%08x slot %d flags %c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2373,7 +2378,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_RESET_EP:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: ctx %08x%08x slot %d ep %d flags %c:%c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2394,7 +2399,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_SET_DEQ:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: deq %08x%08x stream %d slot %d ep %d flags %c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2405,14 +2410,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_RESET_DEV:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: slot %d flags %c",
                        xhci_trb_type_string(type),
                        TRB_TO_SLOT_ID(field3),
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_FORCE_EVENT:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: event %08x%08x vf intr %d vf id %d flags %c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2421,14 +2426,14 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_SET_LT:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: belt %d flags %c",
                        xhci_trb_type_string(type),
                        TRB_TO_BELT(field3),
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_GET_BW:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: ctx %08x%08x slot %d speed %d flags %c",
                        xhci_trb_type_string(type),
                        field1, field0,
@@ -2437,7 +2442,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        case TRB_FORCE_HEADER:
-               sprintf(str,
+               snprintf(str, size,
                        "%s: info %08x%08x%08x pkt type %d roothub port %d flags %c",
                        xhci_trb_type_string(type),
                        field2, field1, field0 & 0xffffffe0,
@@ -2446,7 +2451,7 @@ static inline const char *xhci_decode_trb(u32 field0, u32 field1, u32 field2,
                        field3 & TRB_CYCLE ? 'C' : 'c');
                break;
        default:
-               sprintf(str,
+               snprintf(str, size,
                        "type '%s' -> raw %08x %08x %08x %08x",
                        xhci_trb_type_string(type),
                        field0, field1, field2, field3);
@@ -2571,9 +2576,8 @@ static inline const char *xhci_portsc_link_state_string(u32 portsc)
        return "Unknown";
 }
 
-static inline const char *xhci_decode_portsc(u32 portsc)
+static inline const char *xhci_decode_portsc(char *str, u32 portsc)
 {
-       static char str[256];
        int ret;
 
        ret = sprintf(str, "%s %s %s Link:%s PortSpeed:%d ",