This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Set close-on-exec flag


A gold plugin may exec another program.  In fact, this happens when LTO.
In that case we do not want gold's file descriptors to leak to the other
program.  It's not a security hole, but since gold is file descriptor
hungry it can mean that the other program can't open very many
descriptors of its own.  I committed this patch to set the close-on-exec
flag for every file descriptor opened by gold.  The patch uses O_CLOEXEC
if available.  If it is not available, then we only set FD_CLOEXEC if we
have any plugins, as without any plugins there is no point to making the
extra system call.

Ian


2009-03-17  Ian Lance Taylor  <iant@google.com>

	* descriptors.cc: Include "options.h".
	(FD_CLOEXEC, O_CLOEXEC): Define if not defined.
	(Descriptors::open): Always use O_CLOEXEC when opening a new
	descriptor.  If we have a plugin, and O_CLOEXEC was not defined,
	then set FD_CLOEXEC.


Index: descriptors.cc
===================================================================
RCS file: /cvs/src/src/gold/descriptors.cc,v
retrieving revision 1.4
diff -p -u -r1.4 descriptors.cc
--- descriptors.cc	28 Feb 2009 03:05:08 -0000	1.4
+++ descriptors.cc	17 Mar 2009 17:08:14 -0000
@@ -28,9 +28,20 @@
 #include <unistd.h>
 
 #include "parameters.h"
+#include "options.h"
 #include "gold-threads.h"
 #include "descriptors.h"
 
+// Very old systems may not define FD_CLOEXEC.
+#ifndef FD_CLOEXEC
+#define FD_CLOEXEC 1
+#endif
+
+// O_CLOEXEC is only available on newer systems.
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
 namespace gold
 {
 
@@ -87,6 +98,10 @@ Descriptors::open(int descriptor, const 
 
   while (true)
     {
+      // We always want to set the close-on-exec flag; we don't
+      // require callers to pass it.
+      flags |= O_CLOEXEC;
+
       int new_descriptor = ::open(name, flags, mode);
       if (new_descriptor < 0
 	  && errno != ENFILE
@@ -109,24 +124,35 @@ Descriptors::open(int descriptor, const 
 
       if (new_descriptor >= 0)
 	{
-	  Hold_optional_lock hl(this->lock_);
-
-	  if (static_cast<size_t>(new_descriptor)
-	      >= this->open_descriptors_.size())
-	    this->open_descriptors_.resize(new_descriptor + 64);
+	  // If we have any plugins, we really do need to set the
+	  // close-on-exec flag, even if O_CLOEXEC is not defined.
+	  // FIXME: In some cases O_CLOEXEC may be defined in the
+	  // header file but not supported by the kernel.
+	  // Unfortunately there doesn't seem to be any obvious way to
+	  // detect that, as unknown flags passed to open are ignored.
+	  if (O_CLOEXEC == 0 && parameters->options().has_plugins())
+	    fcntl(new_descriptor, F_SETFD, FD_CLOEXEC);
+
+	  {
+	    Hold_optional_lock hl(this->lock_);
+
+	    if (static_cast<size_t>(new_descriptor)
+		>= this->open_descriptors_.size())
+	      this->open_descriptors_.resize(new_descriptor + 64);
+
+	    Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
+	    pod->name = name;
+	    pod->stack_next = -1;
+	    pod->inuse = true;
+	    pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
+	    pod->is_on_stack = false;
+
+	    ++this->current_;
+	    if (this->current_ >= this->limit_)
+	      this->close_some_descriptor();
 
-	  Open_descriptor* pod = &this->open_descriptors_[new_descriptor];
-	  pod->name = name;
-	  pod->stack_next = -1;
-	  pod->inuse = true;
-	  pod->is_write = (flags & O_ACCMODE) != O_RDONLY;
-	  pod->is_on_stack = false;
-
-	  ++this->current_;
-	  if (this->current_ >= this->limit_)
-	    this->close_some_descriptor();
-
-	  return new_descriptor;
+	    return new_descriptor;
+	  }
 	}
 
       // We ran out of file descriptors.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]