summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2012-02-27 11:19:50 -0500
committerAdam Jackson <ajax@redhat.com>2012-02-27 17:09:01 -0500
commitd2dc9f9daa45504f035b169aba94d0b154fd29f0 (patch)
tree28ccca7fd1ab27a208a9fbd73306c922d19dac86
parentf550c1347d3518874fe1c1d417a57322ee6b52db (diff)
downloadlibpciaccess-d2dc9f9daa45504f035b169aba94d0b154fd29f0.tar.gz
libpciaccess-d2dc9f9daa45504f035b169aba94d0b154fd29f0.tar.bz2
libpciaccess-d2dc9f9daa45504f035b169aba94d0b154fd29f0.zip
Use O_CLOEXEC for internal file descriptors
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@redhat.com>
-rw-r--r--configure.ac1
-rw-r--r--src/common_device_name.c22
-rw-r--r--src/common_vgaarb.c2
-rw-r--r--src/freebsd_pci.c8
-rw-r--r--src/linux_sysfs.c26
-rw-r--r--src/netbsd_pci.c4
-rw-r--r--src/openbsd_pci.c2
-rw-r--r--src/pciaccess_private.h13
-rw-r--r--src/solx_devfs.c6
-rw-r--r--src/x86_pci.c4
10 files changed, 60 insertions, 28 deletions
diff --git a/configure.ac b/configure.ac
index d63ad25..159ddf7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,6 +31,7 @@ AC_CONFIG_HEADERS([config.h])
# Initialize Automake
AM_INIT_AUTOMAKE([foreign dist-bzip2])
AM_MAINTAINER_MODE
+AC_USE_SYSTEM_EXTENSIONS
# Initialize libtool
AC_PROG_LIBTOOL
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..fea9c9f 100644
--- a/src/pciaccess_private.h
+++ b/src/pciaccess_private.h
@@ -37,6 +37,19 @@
# 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.
+ */
+#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)