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, ")"); } }