Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Nov 2012 21:42:24 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r242587 - head/libexec/rtld-elf
Message-ID:  <201211042142.qA4LgOFn060591@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sun Nov  4 21:42:24 2012
New Revision: 242587
URL: http://svn.freebsd.org/changeset/base/242587

Log:
  rtld: Fix fd leak with parallel dlopen and fork/exec.
  
  Rtld did not set FD_CLOEXEC on its internal file descriptors; therefore,
  such a file descriptor may be passed to a process created by another thread
  running in parallel to dlopen() or fdlopen().
  
  No other threads are expected to be running during parsing of the hints
  and libmap files but the file descriptors need not be passed to child
  processes so add O_CLOEXEC there as well.
  
  This change will break fdlopen() (as used by OpenPAM) on kernels without
  F_DUPFD_CLOEXEC (added in July). Note that running new userland on old
  kernels is not supported.
  
  Reviewed by:	kib

Modified:
  head/libexec/rtld-elf/libmap.c
  head/libexec/rtld-elf/rtld.c

Modified: head/libexec/rtld-elf/libmap.c
==============================================================================
--- head/libexec/rtld-elf/libmap.c	Sun Nov  4 21:38:27 2012	(r242586)
+++ head/libexec/rtld-elf/libmap.c	Sun Nov  4 21:42:24 2012	(r242587)
@@ -121,7 +121,7 @@ lmc_parse_file(char *path)
 		}
 	}
 
-	fd = open(rpath, O_RDONLY);
+	fd = open(rpath, O_RDONLY | O_CLOEXEC);
 	if (fd == -1) {
 		dbg("lm_parse_file: open(\"%s\") failed, %s", rpath,
 		    rtld_strerror(errno));

Modified: head/libexec/rtld-elf/rtld.c
==============================================================================
--- head/libexec/rtld-elf/rtld.c	Sun Nov  4 21:38:27 2012	(r242586)
+++ head/libexec/rtld-elf/rtld.c	Sun Nov  4 21:42:24 2012	(r242587)
@@ -1598,7 +1598,7 @@ gethints(bool nostdlib)
 		/* Keep from trying again in case the hints file is bad. */
 		hints = "";
 
-		if ((fd = open(ld_elf_hints_path, O_RDONLY)) == -1)
+		if ((fd = open(ld_elf_hints_path, O_RDONLY | O_CLOEXEC)) == -1)
 			return (NULL);
 		if (read(fd, &hdr, sizeof hdr) != sizeof hdr ||
 		    hdr.magic != ELFHINTS_MAGIC ||
@@ -2046,13 +2046,13 @@ load_object(const char *name, int fd_u, 
      */
     fd = -1;
     if (fd_u == -1) {
-	if ((fd = open(path, O_RDONLY)) == -1) {
+	if ((fd = open(path, O_RDONLY | O_CLOEXEC)) == -1) {
 	    _rtld_error("Cannot open \"%s\"", path);
 	    free(path);
 	    return (NULL);
 	}
     } else {
-	fd = dup(fd_u);
+	fd = fcntl(fd_u, F_DUPFD_CLOEXEC, 0);
 	if (fd == -1) {
 	    _rtld_error("Cannot dup fd");
 	    free(path);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201211042142.qA4LgOFn060591>