Module Name: src
Committed By: snj
Date: Fri Dec 9 04:56:25 UTC 2016
Modified Files:
src/sys/dev/pci [netbsd-7]: pci_subr.c
Log Message:
Pull up following revision(s) (requested by pgoyette in ticket #1296):
sys/dev/pci/pci_subr.c: revision 1.155 via patch
Protect against buffer overflow.
To generate a diff of this commit:
cvs rdiff -u -r1.124.2.2 -r1.124.2.3 src/sys/dev/pci/pci_subr.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/pci/pci_subr.c
diff -u src/sys/dev/pci/pci_subr.c:1.124.2.2 src/sys/dev/pci/pci_subr.c:1.124.2.3
--- src/sys/dev/pci/pci_subr.c:1.124.2.2 Sun Dec 14 16:49:35 2014
+++ src/sys/dev/pci/pci_subr.c Fri Dec 9 04:56:25 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_subr.c,v 1.124.2.2 2014/12/14 16:49:35 martin Exp $ */
+/* $NetBSD: pci_subr.c,v 1.124.2.3 2016/12/09 04:56:25 snj Exp $ */
/*
* Copyright (c) 1997 Zubin D. Dittia. All rights reserved.
@@ -40,7 +40,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.124.2.2 2014/12/14 16:49:35 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.124.2.3 2016/12/09 04:56:25 snj Exp $");
#ifdef _KERNEL_OPT
#include "opt_pci.h"
@@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v
#include <sys/module.h>
#else
#include <pci.h>
+#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
@@ -618,6 +619,43 @@ pci_findproduct_stub(pcireg_t id_reg)
}
#endif
+/*
+ * Append a formatted string to dest without writing more than len
+ * characters (including the trailing NUL character). dest and len
+ * are updated for use in subsequent calls to snappendf().
+ *
+ * Returns 0 on success, a negative value if vnsprintf() fails, or
+ * a positive value if the dest buffer would have overflowed.
+ */
+
+static int __printflike(3,4)
+snappendf(char **dest, size_t *len, const char * restrict fmt, ...)
+{
+ va_list ap;
+ int count;
+
+ va_start(ap, fmt);
+ count = vsnprintf(*dest, *len, fmt, ap);
+ va_end(ap);
+
+ /* Let vsnprintf() errors bubble up to caller */
+ if (count < 0 || *len == 0)
+ return count;
+
+ /* Handle overflow */
+ if ((size_t)count >= *len) {
+ *dest += *len - 1;
+ *len = 1;
+ return 1;
+ }
+
+ /* Update dest & len to point at trailing NUL */
+ *dest += count;
+ *len -= count;
+
+ return 0;
+}
+
void
pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp,
size_t l)
@@ -631,9 +669,6 @@ pci_devinfo(pcireg_t id_reg, pcireg_t cl
const char *unmatched = pci_unmatched;
const char *vendor_namep, *product_namep;
const struct pci_class *classp, *subclassp, *interfacep;
- char *ep;
-
- ep = cp + l;
vendor = PCI_VENDOR(id_reg);
product = PCI_PRODUCT(id_reg);
@@ -669,39 +704,35 @@ pci_devinfo(pcireg_t id_reg, pcireg_t cl
}
if (vendor_namep == NULL)
- cp += snprintf(cp, ep - cp, "%svendor 0x%04x product 0x%04x",
+ (void)snappendf(&cp, &l, "%svendor 0x%04x product 0x%04x",
unmatched, vendor, product);
else if (product_namep != NULL)
- cp += snprintf(cp, ep - cp, "%s %s", vendor_namep,
- product_namep);
+ (void)snappendf(&cp, &l, "%s %s", vendor_namep, product_namep);
else
- cp += snprintf(cp, ep - cp, "%s product 0x%04x",
+ (void)snappendf(&cp, &l, "%s product 0x%04x",
vendor_namep, product);
if (showclass) {
- cp += snprintf(cp, ep - cp, " (");
+ (void)snappendf(&cp, &l, " (");
if (classp->name == NULL)
- cp += snprintf(cp, ep - cp,
+ (void)snappendf(&cp, &l,
"class 0x%02x, subclass 0x%02x", class, subclass);
else {
if (subclassp == NULL || subclassp->name == NULL)
- cp += snprintf(cp, ep - cp,
- "%s, subclass 0x%02x",
+ (void)snappendf(&cp, &l, "%s, subclass 0x%02x",
classp->name, subclass);
else
- cp += snprintf(cp, ep - cp, "%s %s",
+ (void)snappendf(&cp, &l, "%s %s",
subclassp->name, classp->name);
}
if ((interfacep == NULL) || (interfacep->name == NULL)) {
if (interface != 0)
- cp += snprintf(cp, ep - cp,
- ", interface 0x%02x", interface);
+ (void)snappendf(&cp, &l, ", interface 0x%02x",
+ interface);
} else if (strncmp(interfacep->name, "", 1) != 0)
- cp += snprintf(cp, ep - cp, ", %s",
- interfacep->name);
+ (void)snappendf(&cp, &l, ", %s", interfacep->name);
if (revision != 0)
- cp += snprintf(cp, ep - cp, ", revision 0x%02x",
- revision);
- cp += snprintf(cp, ep - cp, ")");
+ (void)snappendf(&cp, &l, ", revision 0x%02x", revision);
+ (void)snappendf(&cp, &l, ")");
}
}