Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
pciutils
lspci-Fixed-buffer-overflows-in-ls-tree.c.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File lspci-Fixed-buffer-overflows-in-ls-tree.c.patch of Package pciutils
From 76d47191f9274991059a41e19e1999a12c0d3416 Mon Sep 17 00:00:00 2001 From: Martin Mares <mj@ucw.cz> Date: Wed, 22 Jan 2020 09:49:18 +0100 Subject: [PATCH] Fixed buffer overflows in ls-tree.c As reported in GitHub issue #24, tree dumping mode can smash the stack if the hierarchy of buses is too deep. Increased line buffer size to 1024 and switched to use of snprintf everywhere, so that in the worst case, the line is truncated. As snprintf can be problematic on obscure platforms, I wrapped it in tree_printf(), so that we can add #ifdefs should problems arise. --- lib/sysdep.h | 2 ++ ls-tree.c | 65 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 47 insertions(+), 22 deletions(-) diff --git a/lib/sysdep.h b/lib/sysdep.h index e525dc4..1a5cb16 100644 --- a/lib/sysdep.h +++ b/lib/sysdep.h @@ -9,9 +9,11 @@ #ifdef __GNUC__ #define UNUSED __attribute__((unused)) #define NONRET __attribute__((noreturn)) +#define FORMAT_CHECK(x,y,z) __attribute__((format(x,y,z))) #else #define UNUSED #define NONRET +#define FORMAT_CHECK(x,y,z) #define inline #endif diff --git a/ls-tree.c b/ls-tree.c index 6995dd2..aeb4087 100644 --- a/ls-tree.c +++ b/ls-tree.c @@ -6,6 +6,7 @@ * Can be freely distributed and used under the terms of the GNU GPL. */ +#include <stdarg.h> #include <stdio.h> #include <string.h> @@ -167,6 +168,31 @@ static void show_tree_bridge(struct bridge *, char *, char *); +#define LINE_BUF_SIZE 1024 + +static char * FORMAT_CHECK(printf, 3, 4) +tree_printf(char *line, char *p, char *fmt, ...) +{ + va_list args; + char *end = line + LINE_BUF_SIZE - 2; + + if (p >= end) + return p; + + va_start(args, fmt); + int res = vsnprintf(p, end - p, fmt, args); + if (res < 0) + { + /* Ancient C libraries return -1 on overflow */ + p += strlen(p); + } + else + p += res; + + va_end(args); + return p; +} + static void show_tree_dev(struct device *d, char *line, char *p) { @@ -174,19 +200,19 @@ struct bridge *b; char namebuf[256]; - p += sprintf(p, "%02x.%x", q->dev, q->func); + p = tree_printf(line, p, "%02x.%x", q->dev, q->func); for (b=&host_bridge; b; b=b->chain) if (b->br_dev == d) { if (b->secondary == b->subordinate) - p += sprintf(p, "-[%02x]-", b->secondary); + p = tree_printf(line, p, "-[%02x]-", b->secondary); else - p += sprintf(p, "-[%02x-%02x]-", b->secondary, b->subordinate); + p = tree_printf(line, p, "-[%02x-%02x]-", b->secondary, b->subordinate); show_tree_bridge(b, line, p); return; } if (verbose) - p += sprintf(p, " %s", + p = tree_printf(line, p, " %s", pci_lookup_name(pacc, namebuf, sizeof(namebuf), PCI_LOOKUP_VENDOR | PCI_LOOKUP_DEVICE, q->vendor_id, q->device_id)); @@ -200,8 +226,7 @@ print_it(line, p); else if (!b->first_dev->next) { - *p++ = '-'; - *p++ = '-'; + p = tree_printf(line, p, "--"); show_tree_dev(b->first_dev, line, p); } else @@ -209,25 +234,23 @@ struct device *d = b->first_dev; while (d->next) { - p[0] = '+'; - p[1] = '-'; - show_tree_dev(d, line, p+2); + char *p2 = tree_printf(line, p, "+-"); + show_tree_dev(d, line, p2); d = d->next; } - p[0] = '\\'; - p[1] = '-'; - show_tree_dev(d, line, p+2); + p = tree_printf(line, p, "\\-"); + show_tree_dev(d, line, p); } } static void show_tree_bridge(struct bridge *b, char *line, char *p) { - *p++ = '-'; + p = tree_printf(line, p, "-"); if (!b->first_bus->sibling) { if (b == &host_bridge) - p += sprintf(p, "[%04x:%02x]-", b->domain, b->first_bus->number); + p = tree_printf(line, p, "[%04x:%02x]-", b->domain, b->first_bus->number); show_tree_bus(b->first_bus, line, p); } else @@ -237,11 +260,11 @@ while (u->sibling) { - k = p + sprintf(p, "+-[%04x:%02x]-", u->domain, u->number); + k = tree_printf(line, p, "+-[%04x:%02x]-", u->domain, u->number); show_tree_bus(u, line, k); u = u->sibling; } - k = p + sprintf(p, "\\-[%04x:%02x]-", u->domain, u->number); + k = tree_printf(line, p, "\\-[%04x:%02x]-", u->domain, u->number); show_tree_bus(u, line, k); } } @@ -249,7 +272,7 @@ void show_forest(void) { - char line[256]; + char line[LINE_BUF_SIZE]; grow_tree(); show_tree_bridge(&host_bridge, line, line);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor