[PATCH] Use O_CLOEXEC for internal file descriptors

Adam Jackson ajax at redhat.com
Mon Feb 27 08:35:20 PST 2012


Well, almost all of them.  zlib doesn't support "e" in the mode string
in gzopen() though it will silently accept and ignore it, and Solaris appears
not to support "e" in the mode string at all.

Signed-off-by: Adam Jackson <ajax at redhat.com>
---
 src/common_device_name.c |   22 ++++++++++++++++++++--
 src/common_vgaarb.c      |    2 +-
 src/freebsd_pci.c        |    8 ++++----
 src/linux_sysfs.c        |   26 +++++++++++++-------------
 src/netbsd_pci.c         |    4 ++--
 src/openbsd_pci.c        |    2 +-
 src/pciaccess_private.h  |   19 +++++++++++++++++++
 src/solx_devfs.c         |    6 +++---
 src/x86_pci.c            |    4 ++--
 9 files changed, 65 insertions(+), 28 deletions(-)

diff --git a/src/common_device_name.c b/src/common_device_name.c
index b2765dd..ad9ed9d 100644
--- a/src/common_device_name.c
+++ b/src/common_device_name.c
@@ -51,6 +51,7 @@
 #define DO_MATCH(a,b)  (((a) == PCI_MATCH_ANY) || ((a) == (b)))
 
 #ifdef HAVE_ZLIB
+
 #include <zlib.h>
 typedef gzFile pci_id_file;
 
@@ -68,11 +69,28 @@ pci_id_file_open(void)
 
 #define pci_id_file_gets(l, s, f)	gzgets(f, l, s)
 #define pci_id_file_close(f)		gzclose(f)
-#else
+
+#else /* not zlib */
+
 typedef FILE * pci_id_file;
-#define pci_id_file_open()		fopen(PCIIDS_PATH "/pci.ids", "r")
+
+static pci_id_file
+pci_id_file_open(void)
+{
+    pci_id_file result;
+
+#ifndef __sun
+    result = fopen(PCIIDS_PATH "/pci.ids", "re");
+    if (result)
+        return result;
+#endif
+
+    return fopen(PCIIDS_PATH "/pci.ids", "r");
+}
+
 #define pci_id_file_gets(l, s, f)	fgets(l, s, f)
 #define pci_id_file_close(f)		fclose(f)
+
 #endif
 
 /**
diff --git a/src/common_vgaarb.c b/src/common_vgaarb.c
index 86eceb5..ab3c5e8 100644
--- a/src/common_vgaarb.c
+++ b/src/common_vgaarb.c
@@ -129,7 +129,7 @@ pci_device_vgaarb_init(void)
     if (!pci_sys)
         return -1;
 
-    if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR)) < 0) {
+    if ((pci_sys->vgaarb_fd = open ("/dev/vga_arbiter", O_RDWR | O_CLOEXEC)) < 0) {
         return errno;
     }
 
diff --git a/src/freebsd_pci.c b/src/freebsd_pci.c
index d11535d..cc50e91 100644
--- a/src/freebsd_pci.c
+++ b/src/freebsd_pci.c
@@ -108,7 +108,7 @@ pci_device_freebsd_map_range(struct pci_device *dev,
 
     int fd, err = 0;
 
-    fd = open("/dev/mem", O_RDWR);
+    fd = open("/dev/mem", O_RDWR | O_CLOEXEC);
     if (fd == -1)
 	return errno;
 
@@ -153,7 +153,7 @@ pci_device_freebsd_unmap_range( struct pci_device *dev,
     if ((map->flags & PCI_DEV_MAP_FLAG_CACHABLE) ||
 	(map->flags & PCI_DEV_MAP_FLAG_WRITE_COMBINE))
     {
-	fd = open("/dev/mem", O_RDWR);
+	fd = open("/dev/mem", O_RDWR | O_CLOEXEC);
 	if (fd != -1) {
 	    mrd.mr_base = map->base;
 	    mrd.mr_len = map->size;
@@ -293,7 +293,7 @@ pci_device_freebsd_read_rom( struct pci_device * dev, void * buffer )
     }
 
     printf("Using rom_base = 0x%lx\n", (long)rom_base);
-    memfd = open( "/dev/mem", O_RDONLY );
+    memfd = open( "/dev/mem", O_RDONLY | O_CLOEXEC );
     if ( memfd == -1 )
 	return errno;
 
@@ -585,7 +585,7 @@ pci_system_freebsd_create( void )
     int i;
 
     /* Try to open the PCI device */
-    pcidev = open( "/dev/pci", O_RDWR );
+    pcidev = open( "/dev/pci", O_RDWR | O_CLOEXEC );
     if ( pcidev == -1 )
 	return ENXIO;
 
diff --git a/src/linux_sysfs.c b/src/linux_sysfs.c
index 9566d40..b817860 100644
--- a/src/linux_sysfs.c
+++ b/src/linux_sysfs.c
@@ -98,7 +98,7 @@ pci_system_linux_sysfs_create( void )
 	if ( pci_sys != NULL ) {
 	    pci_sys->methods = & linux_sysfs_methods;
 #ifdef HAVE_MTRR
-	    pci_sys->mtrr_fd = open("/proc/mtrr", O_WRONLY);
+	    pci_sys->mtrr_fd = open("/proc/mtrr", O_WRONLY | O_CLOEXEC);
 #endif
 	    err = populate_entries(pci_sys);
 	}
@@ -245,7 +245,7 @@ pci_device_linux_sysfs_probe( struct pci_device * dev )
 		  dev->bus,
 		  dev->dev,
 		  dev->func );
-	fd = open( name, O_RDONLY );
+	fd = open( name, O_RDONLY | O_CLOEXEC);
 	if ( fd != -1 ) {
 	    char * next;
 	    pciaddr_t  low_addr;
@@ -307,7 +307,7 @@ pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer )
 	      dev->dev,
 	      dev->func );
 
-    fd = open( name, O_RDWR );
+    fd = open( name, O_RDWR | O_CLOEXEC);
     if ( fd == -1 ) {
 #ifdef LINUX_ROM
 	/* If reading the ROM using sysfs fails, fall back to the old
@@ -388,7 +388,7 @@ pci_device_linux_sysfs_read( struct pci_device * dev, void * data,
 	      dev->dev,
 	      dev->func );
 
-    fd = open( name, O_RDONLY );
+    fd = open( name, O_RDONLY | O_CLOEXEC);
     if ( fd == -1 ) {
 	return errno;
     }
@@ -448,7 +448,7 @@ pci_device_linux_sysfs_write( struct pci_device * dev, const void * data,
 	      dev->dev,
 	      dev->func );
 
-    fd = open( name, O_WRONLY );
+    fd = open( name, O_WRONLY | O_CLOEXEC);
     if ( fd == -1 ) {
 	return errno;
     }
@@ -499,7 +499,7 @@ pci_device_linux_sysfs_map_range_wc(struct pci_device *dev,
 	     dev->dev,
 	     dev->func,
 	     map->region);
-    fd = open(name, open_flags);
+    fd = open(name, open_flags | O_CLOEXEC);
     if (fd == -1)
 	    return errno;
 
@@ -564,7 +564,7 @@ pci_device_linux_sysfs_map_range(struct pci_device *dev,
              dev->func,
              map->region);
 
-    fd = open(name, open_flags);
+    fd = open(name, open_flags | O_CLOEXEC);
     if (fd == -1) {
         return errno;
     }
@@ -687,7 +687,7 @@ static void pci_device_linux_sysfs_enable(struct pci_device *dev)
 	      dev->dev,
 	      dev->func );
 
-    fd = open( name, O_RDWR );
+    fd = open( name, O_RDWR | O_CLOEXEC);
     if (fd == -1)
        return;
 
@@ -709,7 +709,7 @@ static int pci_device_linux_sysfs_boot_vga(struct pci_device *dev)
 	      dev->dev,
 	      dev->func );
 
-    fd = open( name, O_RDONLY );
+    fd = open( name, O_RDONLY | O_CLOEXEC);
     if (fd == -1)
        return 0;
 
@@ -752,7 +752,7 @@ pci_device_linux_sysfs_open_device_io(struct pci_io_handle *ret,
     snprintf(name, PATH_MAX, "%s/%04x:%02x:%02x.%1u/resource%d",
 	     SYS_BUS_PCI, dev->domain, dev->bus, dev->dev, dev->func, bar);
 
-    ret->fd = open(name, O_RDWR);
+    ret->fd = open(name, O_RDWR | O_CLOEXEC);
 
     if (ret->fd < 0)
 	return NULL;
@@ -775,7 +775,7 @@ pci_device_linux_sysfs_open_legacy_io(struct pci_io_handle *ret,
 	snprintf(name, PATH_MAX, "/sys/class/pci_bus/%04x:%02x/legacy_io",
 		 dev->domain, dev->bus);
 
-	ret->fd = open(name, O_RDWR);
+	ret->fd = open(name, O_RDWR | O_CLOEXEC);
 	if (ret->fd >= 0)
 	    break;
 
@@ -897,7 +897,7 @@ pci_device_linux_sysfs_map_legacy(struct pci_device *dev, pciaddr_t base,
 	snprintf(name, PATH_MAX, "/sys/class/pci_bus/%04x:%02x/legacy_mem",
 		 dev->domain, dev->bus);
 
-	fd = open(name, flags);
+	fd = open(name, flags | O_CLOEXEC);
 	if (fd >= 0)
 	    break;
 
@@ -906,7 +906,7 @@ pci_device_linux_sysfs_map_legacy(struct pci_device *dev, pciaddr_t base,
 
     /* If not, /dev/mem is the best we can do */
     if (!dev)
-	fd = open("/dev/mem", flags);
+	fd = open("/dev/mem", flags | O_CLOEXEC);
 
     if (fd < 0)
 	return errno;
diff --git a/src/netbsd_pci.c b/src/netbsd_pci.c
index d351e8f..63585e3 100644
--- a/src/netbsd_pci.c
+++ b/src/netbsd_pci.c
@@ -94,7 +94,7 @@ pci_device_netbsd_map_range(struct pci_device *dev,
 	struct mtrr mtrr;
 	int fd, error, nmtrr, prot = PROT_READ;
 
-	if ((fd = open("/dev/mem", O_RDWR)) == -1)
+	if ((fd = open("/dev/mem", O_RDWR | O_CLOEXEC)) == -1)
 		return errno;
 
 	if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE)
@@ -328,7 +328,7 @@ pci_system_netbsd_create(void)
 	int bus, dev, func, ndevs, nfuncs;
 	uint32_t reg;
 
-	pcifd = open("/dev/pci0", O_RDWR);
+	pcifd = open("/dev/pci0", O_RDWR | O_CLOEXEC);
 	if (pcifd == -1)
 		return ENXIO;
 
diff --git a/src/openbsd_pci.c b/src/openbsd_pci.c
index 14e976d..74b3636 100644
--- a/src/openbsd_pci.c
+++ b/src/openbsd_pci.c
@@ -568,7 +568,7 @@ pci_system_openbsd_create(void)
 
 	for (domain = 0; domain < sizeof(pcifd) / sizeof(pcifd[0]); domain++) {
 		snprintf(path, sizeof(path), "/dev/pci%d", domain);
-	        pcifd[domain] = open(path, O_RDWR);
+	        pcifd[domain] = open(path, O_RDWR | O_CLOEXEC);
 		if (pcifd[domain] == -1)
 			break;
 		ndomains++;
diff --git a/src/pciaccess_private.h b/src/pciaccess_private.h
index 32f8a75..0d4b9e9 100644
--- a/src/pciaccess_private.h
+++ b/src/pciaccess_private.h
@@ -37,6 +37,25 @@
 # define _pci_hidden
 #endif /* GNUC >= 4 */
 
+/*
+ * O_CLOEXEC fixes an fd leak case (see 'man 2 open' for details). I don't
+ * know of any OS we support where this isn't available in a sufficiently
+ * new version, so warn unconditionally.
+ *
+ * Of course, on Linux, you don't get this unless you ask for it, so ask
+ * for it first.
+ */
+#if defined(linux) && !defined(__GNU_SOURCE)
+#define __GNU_SOURCE
+#endif
+#include <sys/fcntl.h>
+
+#ifndef O_CLOEXEC
+#warning O_CLOEXEC not available, please upgrade.
+#define O_CLOEXEC 0
+#endif
+
+
 struct pci_device_mapping;
 
 int pci_fill_capabilities_generic( struct pci_device * dev );
diff --git a/src/solx_devfs.c b/src/solx_devfs.c
index 5e91a14..2079df0 100644
--- a/src/solx_devfs.c
+++ b/src/solx_devfs.c
@@ -663,7 +663,7 @@ probe_nexus_node(di_node_t di_node, di_minor_t minor, void *arg)
 	    nexus_path, first_bus, last_bus);
 #endif
 
-    if ((fd = open(nexus_path, O_RDWR)) >= 0) {
+    if ((fd = open(nexus_path, O_RDWR | O_CLOEXEC)) >= 0) {
 	nexus->fd = fd;
 	nexus->path = strdup(nexus_path);
 	nexus_dev_path = di_devfs_path(di_node);
@@ -931,7 +931,7 @@ pci_device_solx_devfs_map_range(struct pci_device *dev,
     else
 	strcpy (map_dev, "/dev/fb0");
 
-    if ((map_fd = open(map_dev, O_RDWR)) < 0) {
+    if ((map_fd = open(map_dev, O_RDWR | O_CLOEXEC)) < 0) {
 	err = errno;
 	(void) fprintf(stderr, "can not open %s: %s\n", map_dev,
 			   strerror(errno));
@@ -944,7 +944,7 @@ pci_device_solx_devfs_map_range(struct pci_device *dev,
      * Still used xsvc to do the user space mapping
      */
     if (xsvc_fd < 0) {
-	if ((xsvc_fd = open("/dev/xsvc", O_RDWR)) < 0) {
+	if ((xsvc_fd = open("/dev/xsvc", O_RDWR | O_CLOEXEC)) < 0) {
 	    err = errno;
 	    (void) fprintf(stderr, "can not open /dev/xsvc: %s\n",
 			   strerror(errno));
diff --git a/src/x86_pci.c b/src/x86_pci.c
index c42d3e0..78e5f6c 100644
--- a/src/x86_pci.c
+++ b/src/x86_pci.c
@@ -330,7 +330,7 @@ pci_device_x86_read_rom(struct pci_device *dev, void *buffer)
 	return ENOSYS;
     }
 
-    memfd = open("/dev/mem", O_RDONLY);
+    memfd = open("/dev/mem", O_RDONLY | O_CLOEXEC);
     if (memfd == -1)
 	return errno;
 
@@ -475,7 +475,7 @@ static int
 pci_device_x86_map_range(struct pci_device *dev,
     struct pci_device_mapping *map)
 {
-    int memfd = open("/dev/mem", O_RDWR);
+    int memfd = open("/dev/mem", O_RDWR | O_CLOEXEC);
     int prot = PROT_READ;
 
     if (memfd == -1)
-- 
1.7.7.6



More information about the xorg-devel mailing list