[PATCH] libpciaccess: fix memory usage errors

Mark Logan mark.logan at oracle.com
Tue Sep 18 13:28:18 PDT 2012


 From 5e4a79958e74783cb3ee3e58b183cdcff82daf2b Mon Sep 17 00:00:00 2001
From: Mark Logan<mark.logan at oracle.com>
Date: Tue, 18 Sep 2012 09:07:04 -0700
Subject: [PATCH] This patch fixes memory usage errors that only occur on
  large SPARC machines with more than 256 PCI devices. In
  this case, memory is being used after it has been freed by
  calls to both free() and realloc(). This error was
  introduced by a previous patch: 2011-03-30	Solaris
  support for multiple PCI segments (domains)

Signed-off-by: Mark Logan<mark.logan at oracle.com>
---
  src/common_init.c |  9 ++++++++-
  src/solx_devfs.c  | 23 +++++++++++++----------
  2 files changed, 21 insertions(+), 11 deletions(-)

diff --git a/src/common_init.c b/src/common_init.c
index 5e91c27..b20d3d5 100644
--- a/src/common_init.c
+++ b/src/common_init.c
@@ -112,15 +112,22 @@ pci_system_cleanup( void )
  	    }
  	}
  
+#ifdef __sparc
+	if ( pci_sys->methods->destroy != NULL ) {
+	    (*pci_sys->methods->destroy)();
+	}
+#endif
+
  	free( pci_sys->devices );
  	pci_sys->devices = NULL;
  	pci_sys->num_devices = 0;
      }
  
-
+#ifndef __sparc
      if ( pci_sys->methods->destroy != NULL ) {
  	(*pci_sys->methods->destroy)();
      }
+#endif
  
      free( pci_sys );
      pci_sys = NULL;
diff --git a/src/solx_devfs.c b/src/solx_devfs.c
index 3eefefb..bb97f56 100644
--- a/src/solx_devfs.c
+++ b/src/solx_devfs.c
@@ -72,7 +72,7 @@ typedef struct nexus {
      char *dev_path;
      struct nexus *next;
  #ifdef __sparc
-    struct pci_device **devlist;
+    size_t *devlist;
      volatile size_t num_allocated_elems;
      volatile size_t num_devices;
  #endif
@@ -140,7 +140,8 @@ find_nexus_for_dev(struct pci_device *dev)
  
      for (nexus = nexus_list ; nexus != NULL ; nexus = nexus->next) {
  	for (i = 0; i < nexus->num_devices; i++) {
-	    if (nexus->devlist[i] == dev)
+	    size_t dev_idx = nexus->devlist[i];
+	    if (&pci_sys->devices[dev_idx].base == dev)
  		return nexus;
  	}
      }
@@ -196,7 +197,8 @@ pci_system_solx_devfs_destroy( void )
  	    int i;
  
  	    for (i = 0; i < nexus->num_devices; i++) {
-		dev = nexus->devlist[i];
+		size_t dev_idx = nexus->devlist[i];
+		dev = &pci_sys->devices[dev_idx].base;
  		if (MAPPING_DEV_PATH(dev))
  		    di_devfs_path_free((char *) MAPPING_DEV_PATH(dev));
  	    }
@@ -383,7 +385,8 @@ probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, probe_info_t *pinfo)
  	     * function number.
  	     */
  
-	    pci_base = &pinfo->devices[pinfo->num_devices].base;
+	    size_t dev_idx = pinfo->num_devices;
+	    pci_base = &pinfo->devices[dev_idx].base;
  
  	    pci_base->domain = nexus->domain;
  	    pci_base->bus = prg_p->bus_no;
@@ -406,7 +409,7 @@ probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, probe_info_t *pinfo)
  	    pci_base->subdevice_id 	= GET_CONFIG_VAL_16(PCI_CONF_SUBSYSID);
  	    pci_base->irq		= GET_CONFIG_VAL_8(PCI_CONF_ILINE);
  
-	    pinfo->devices[pinfo->num_devices].header_type
+	    pinfo->devices[dev_idx].header_type
  					= GET_CONFIG_VAL_8(PCI_CONF_HEADER);
  
  #ifdef DEBUG
@@ -437,19 +440,19 @@ probe_dev(nexus_t *nexus, pcitool_reg_t *prg_p, probe_info_t *pinfo)
  	    }
  
  #ifdef __sparc
-	    nexus->devlist[nexus->num_devices++] = pci_base;
+	    nexus->devlist[nexus->num_devices++] = dev_idx;
  
  	    if (nexus->num_devices == nexus->num_allocated_elems) {
-		struct pci_device **new_devs;
+		size_t *new_devs;
  		size_t new_num_elems = nexus->num_allocated_elems * 2;
  
  		new_devs = realloc(nexus->devlist,
-			new_num_elems * sizeof (struct pci_device *));
+			new_num_elems * sizeof (size_t *));
  		if (new_devs == NULL)
  		    return (rval);
  		(void) memset(&new_devs[nexus->num_devices], 0,
  			nexus->num_allocated_elems *
-			sizeof (struct pci_device *));
+			sizeof (size_t *));
  		nexus->num_allocated_elems = new_num_elems;
  		nexus->devlist = new_devs;
  	    }
@@ -642,7 +645,7 @@ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
  
  #ifdef __sparc
      if ((nexus->devlist = calloc(INITIAL_NUM_DEVICES,
-			sizeof (struct pci_device *))) == NULL) {
+			sizeof (size_t *))) == NULL) {
  	(void) fprintf(stderr, "Error allocating memory for nexus devlist: %s\n",
                         strerror(errno));
  	free (nexus);
-- 1.7.11.msysgit.1



More information about the xorg-devel mailing list