Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > ebe084c140192657f9094e135a84202c > files > 138

libvirt-0.8.2-29.el5.src.rpm

From 0e9d3b567d54beabd722dabaeb78001959153196 Mon Sep 17 00:00:00 2001
From: Eric Blake <eblake@redhat.com>
Date: Wed, 20 Jun 2012 19:19:16 -0600
Subject: [PATCH] util: avoid PATH_MAX-sized array
To: libvir-list@redhat.com

https://bugzilla.redhat.com/show_bug.cgi?id=816601
CVE-2012-2693

See previous patch for why this is good...

[from the previous patch aa286e5]:
    POSIX allows implementations where PATH_MAX is undefined, leading
    to compilation error.  Not to mention that even if it is defined,
    it is often wasteful in relation to the amount of data being stored.

* src/util/pci.c (struct _pciDevice, pciGetDevice, pciFreeDevice):
Manage path dynamically.  Report snprintf overflow.
* src/util/hostusb.c (struct _usbDevice, usbGetDevice)
(usbFreeDevice): Likewise.
(cherry picked from commit 60bfd5b5653b85c9c7950927c3265025630e8300)

Signed-off-by: Daniel Veillard <veillard@redhat.com>
---
 src/util/hostusb.c |   32 +++++++++++++++++++++++++-------
 src/util/pci.c     |   31 +++++++++++++++++++++++++------
 2 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/src/util/hostusb.c b/src/util/hostusb.c
index 2d6e414..79bf030 100644
--- a/src/util/hostusb.c
+++ b/src/util/hostusb.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009-2010 Red Hat, Inc.
+ * Copyright (C) 2009-2011 Red Hat, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -48,7 +48,7 @@ struct _usbDevice {
 
     char          name[USB_ADDR_LEN]; /* domain:bus:slot.function */
     char          id[USB_ID_LEN];     /* product vendor */
-    char          path[PATH_MAX];
+    char          *path;
 };
 
 /* For virReportOOMError()  and virReportSystemError() */
@@ -171,13 +171,30 @@ usbGetDevice(unsigned bus,
     dev->bus     = bus;
     dev->dev     = devno;
 
-    snprintf(dev->name, sizeof(dev->name), "%.3o:%.3o",
-             dev->bus, dev->dev);
-    snprintf(dev->path, sizeof(dev->path),
-             USB_DEVFS "%03d/%03d", dev->bus, dev->dev);
+    if (snprintf(dev->name, sizeof(dev->name), "%.3o:%.3o",
+                 dev->bus, dev->dev) >= sizeof(dev->name)) {
+        usbReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->name buffer overflow: %.3o:%.3o"),
+                       dev->bus, dev->dev);
+        usbFreeDevice(dev);
+        return NULL;
+    }
+    if (virAsprintf(&dev->path, USB_DEVFS "%03d/%03d",
+                    dev->bus, dev->dev) < 0) {
+        virReportOOMError();
+        usbFreeDevice(dev);
+        return NULL;
+    }
 
     /* XXX fixme. this should be product/vendor */
-    snprintf(dev->id, sizeof(dev->id), "%d %d", dev->bus, dev->dev);
+    if (snprintf(dev->id, sizeof(dev->id), "%d %d", dev->bus,
+                 dev->dev) >= sizeof(dev->id)) {
+        usbReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->id buffer overflow: %d %d"),
+                       dev->bus, dev->dev);
+        usbFreeDevice(dev);
+        return NULL;
+    }
 
     VIR_DEBUG("%s %s: initialized", dev->id, dev->name);
 
@@ -203,6 +220,7 @@ void
 usbFreeDevice(usbDevice *dev)
 {
     VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
+    VIR_FREE(dev->path);
     VIR_FREE(dev);
 }
 
diff --git a/src/util/pci.c b/src/util/pci.c
index b07ff96..dfa539d 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -55,7 +55,7 @@ struct _pciDevice {
 
     char          name[PCI_ADDR_LEN]; /* domain:bus:slot.function */
     char          id[PCI_ID_LEN];     /* product vendor */
-    char          path[PATH_MAX];
+    char          *path;
     int           fd;
 
     unsigned      initted;
@@ -1147,10 +1147,21 @@ pciGetDevice(unsigned domain,
     dev->slot     = slot;
     dev->function = function;
 
-    snprintf(dev->name, sizeof(dev->name), "%.4x:%.2x:%.2x.%.1x",
-             dev->domain, dev->bus, dev->slot, dev->function);
-    snprintf(dev->path, sizeof(dev->path),
-             PCI_SYSFS "devices/%s/config", dev->name);
+    if (snprintf(dev->name, sizeof(dev->name), "%.4x:%.2x:%.2x.%.1x",
+                 dev->domain, dev->bus, dev->slot,
+                 dev->function) >= sizeof(dev->name)) {
+        pciReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->name buffer overflow: %.4x:%.2x:%.2x.%.1x"),
+                       dev->domain, dev->bus, dev->slot, dev->function);
+        pciFreeDevice(dev);
+        return NULL;
+    }
+    if (virAsprintf(&dev->path, PCI_SYSFS "devices/%s/config",
+                    dev->name) < 0) {
+        virReportOOMError();
+        pciFreeDevice(dev);
+        return NULL;
+    }
 
     if (access(dev->path, F_OK) != 0) {
         virReportSystemError(errno,
@@ -1174,7 +1185,14 @@ pciGetDevice(unsigned domain,
     }
 
     /* strings contain '0x' prefix */
-    snprintf(dev->id, sizeof(dev->id), "%s %s", &vendor[2], &product[2]);
+    if (snprintf(dev->id, sizeof(dev->id), "%s %s", &vendor[2],
+                 &product[2]) >= sizeof(dev->id)) {
+        pciReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("dev->id buffer overflow: %s %s"),
+                       &vendor[2], &product[2]);
+        pciFreeDevice(dev);
+        return NULL;
+    }
 
     VIR_FREE(product);
     VIR_FREE(vendor);
@@ -1191,6 +1209,7 @@ pciFreeDevice(pciDevice *dev)
         return;
     VIR_DEBUG("%s %s: freeing", dev->id, dev->name);
     pciCloseConfig(dev);
+    VIR_FREE(dev->path);
     VIR_FREE(dev);
 }
 
-- 
1.7.7.4