Browse Source

Merge remote branch 'sjmurdoch/cloexec'

Nick Mathewson 15 years ago
parent
commit
9908404f01
9 changed files with 87 additions and 19 deletions
  1. 1 0
      configure.in
  2. 59 4
      src/common/compat.c
  3. 5 0
      src/common/compat.h
  4. 1 1
      src/common/log.c
  5. 14 7
      src/common/util.c
  6. 2 2
      src/or/connection_edge.c
  7. 1 1
      src/or/dirserv.c
  8. 3 3
      src/or/eventdns.c
  9. 1 1
      src/or/geoip.c

+ 1 - 0
configure.in

@@ -250,6 +250,7 @@ dnl Check for functions before libevent, since libevent-1.2 apparently
 dnl exports strlcpy without defining it in a header.
 
 AC_CHECK_FUNCS(
+	accept4 \
         flock \
         ftime \
         getaddrinfo \

+ 59 - 4
src/common/compat.c

@@ -101,6 +101,35 @@
 #include "strlcat.c"
 #endif
 
+/** As open(path, flags, mode), but return an fd with the close-on-exec mode
+ * set. */
+int
+tor_open_cloexec(const char *path, int flags, unsigned mode)
+{
+#ifdef O_CLOEXEC
+  return open(path, flags|O_CLOEXEC, mode);
+#else
+  int fd = open(path, flags, mode);
+#ifdef FD_CLOEXEC
+  if (fd >= 0)
+        fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+  return fd;
+#endif
+}
+
+/** DOCDOC */
+FILE *
+tor_fopen_cloexec(const char *path, const char *mode)
+{
+  FILE *result = fopen(path, mode);
+#ifdef FD_CLOEXEC
+  if (result != NULL)
+    fcntl(fileno(result), F_SETFD, FD_CLOEXEC);
+#endif
+  return result;
+}
+
 #ifdef HAVE_SYS_MMAN_H
 /** Try to create a memory mapping for <b>filename</b> and return it.  On
  * failure, return NULL.  Sets errno properly, using ERANGE to mean
@@ -116,7 +145,7 @@ tor_mmap_file(const char *filename)
 
   tor_assert(filename);
 
-  fd = open(filename, O_RDONLY, 0);
+  fd = tor_open_cloexec(filename, O_RDONLY, 0);
   if (fd<0) {
     int save_errno = errno;
     int severity = (errno == ENOENT) ? LOG_INFO : LOG_WARN;
@@ -685,7 +714,7 @@ tor_lockfile_lock(const char *filename, int blocking, int *locked_out)
   *locked_out = 0;
 
   log_info(LD_FS, "Locking \"%s\"", filename);
-  fd = open(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+  fd = tor_open_cloexec(filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
   if (fd < 0) {
     log_warn(LD_FS,"Couldn't open \"%s\" for locking: %s", filename,
              strerror(errno));
@@ -904,8 +933,16 @@ mark_socket_open(int s)
 int
 tor_open_socket(int domain, int type, int protocol)
 {
-  int s = socket(domain, type, protocol);
+  int s;
+#ifdef SOCK_CLOEXEC
+#define LINUX_CLOEXEC_OPEN_SOCKET
+  type |= SOCK_CLOEXEC;
+#endif
+  s = socket(domain, type, protocol);
   if (s >= 0) {
+#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC)
+    fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
     socket_accounting_lock();
     ++n_sockets_open;
     mark_socket_open(s);
@@ -918,8 +955,17 @@ tor_open_socket(int domain, int type, int protocol)
 int
 tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len)
 {
-  int s = accept(sockfd, addr, len);
+  int s;
+#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC)
+#define LINUX_CLOEXEC_ACCEPT
+  s = accept4(sockfd, addr, len, SOCK_CLOEXEC);
+#else
+  s = accept(sockfd, addr, len);
+#endif
   if (s >= 0) {
+#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC)
+    fcntl(s, F_SETFD, FD_CLOEXEC);
+#endif
     socket_accounting_lock();
     ++n_sockets_open;
     mark_socket_open(s);
@@ -975,8 +1021,17 @@ tor_socketpair(int family, int type, int protocol, int fd[2])
 //don't use win32 socketpairs (they are always bad)
 #if defined(HAVE_SOCKETPAIR) && !defined(MS_WINDOWS)
   int r;
+#ifdef SOCK_CLOEXEC
+  type |= SOCK_CLOEXEC;
+#endif
   r = socketpair(family, type, protocol, fd);
   if (r == 0) {
+#if !defined(SOCK_CLOEXEC) && defined(FD_CLOEXEC)
+    if (fd[0] >= 0)
+      fcntl(fd[0], F_SETFD, FD_CLOEXEC);
+    if (fd[1] >= 0)
+      fcntl(fd[1], F_SETFD, FD_CLOEXEC);
+#endif
     socket_accounting_lock();
     if (fd[0] >= 0) {
       ++n_sockets_open;

+ 5 - 0
src/common/compat.h

@@ -51,6 +51,8 @@
 #include <netinet6/in6.h>
 #endif
 
+#include <stdio.h>
+
 #if defined (WINCE)
 #include <fcntl.h>
 #include <io.h>
@@ -340,6 +342,9 @@ struct tm *tor_gmtime_r(const time_t *timep, struct tm *result);
    ((tvp)->tv_sec cmp  (uvp)->tv_sec))
 
 /* ===== File compatibility */
+int tor_open_cloexec(const char *path, int flags, unsigned mode);
+FILE *tor_fopen_cloexec(const char *path, const char *mode);
+
 int replace_file(const char *from, const char *to);
 int touch_file(const char *fname);
 

+ 1 - 1
src/common/log.c

@@ -686,7 +686,7 @@ add_file_log(const log_severity_list_t *severity, const char *filename)
   int fd;
   logfile_t *lf;
 
-  fd = open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
+  fd = tor_open_cloexec(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
   if (fd<0)
     return -1;
   if (tor_fd_seekend(fd)<0)

+ 14 - 7
src/common/util.c

@@ -1814,7 +1814,7 @@ start_writing_to_file(const char *fname, int open_flags, int mode,
   if (open_flags & O_BINARY)
     new_file->binary = 1;
 
-  new_file->fd = open(open_name, open_flags, mode);
+  new_file->fd = tor_open_cloexec(open_name, open_flags, mode);
   if (new_file->fd < 0) {
     log_warn(LD_FS, "Couldn't open \"%s\" (%s) for writing: %s",
         open_name, fname, strerror(errno));
@@ -2035,7 +2035,7 @@ read_file_to_str(const char *filename, int flags, struct stat *stat_out)
 
   tor_assert(filename);
 
-  fd = open(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
+  fd = tor_open_cloexec(filename,O_RDONLY|(bin?O_BINARY:O_TEXT),0);
   if (fd<0) {
     int severity = LOG_WARN;
     int save_errno = errno;
@@ -2735,7 +2735,7 @@ finish_daemon(const char *desired_cwd)
     exit(1);
   }
 
-  nullfd = open("/dev/null", O_RDWR);
+  nullfd = tor_open_cloexec("/dev/null", O_RDWR, 0);
   if (nullfd < 0) {
     log_err(LD_GENERAL,"/dev/null can't be opened. Exiting.");
     exit(1);
@@ -2986,7 +2986,7 @@ tor_spawn_background(const char *const filename, int *stdout_read,
     child_state = CHILD_STATE_REDIRECT;
 
     /* Link stdin to /dev/null */
-    fd = open("/dev/null", O_RDONLY);
+    fd = open("/dev/null", O_RDONLY); /* NOT cloexec, obviously. */
     if (fd != -1)
       dup2(STDIN_FILENO, fd);
     else
@@ -2994,11 +2994,18 @@ tor_spawn_background(const char *const filename, int *stdout_read,
 
     child_state = CHILD_STATE_CLOSEFD;
 
+    close(stderr_pipe[0]);
+    close(stderr_pipe[1]);
+    close(stdout_pipe[0]);
+    close(stdout_pipe[1]);
+    close(fd);
+
     /* Close all other fds, including the read end of the pipe */
-    /* XXX: use closefrom if available, or better still set FD_CLOEXEC
-       on all of Tor's open files */
-    for (fd = STDERR_FILENO + 1; fd < max_fd; fd++)
+    /* XXX: We should now be doing enough FD_CLOEXEC setting to make
+     * this needless. */
+    for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) {
       close(fd);
+    }
 
     child_state = CHILD_STATE_EXEC;
 

+ 2 - 2
src/or/connection_edge.c

@@ -1752,10 +1752,10 @@ get_pf_socket(void)
 
 #ifdef OPENBSD
   /* only works on OpenBSD */
-  pf = open("/dev/pf", O_RDONLY);
+  pf = tor_open_cloexec("/dev/pf", O_RDONLY, 0);
 #else
   /* works on NetBSD and FreeBSD */
-  pf = open("/dev/pf", O_RDWR);
+  pf = tor_open_cloexec("/dev/pf", O_RDWR, 0);
 #endif
 
   if (pf < 0) {

+ 1 - 1
src/or/dirserv.c

@@ -2446,7 +2446,7 @@ dirserv_read_measured_bandwidths(const char *from_file,
                                  smartlist_t *routerstatuses)
 {
   char line[256];
-  FILE *fp = fopen(from_file, "r");
+  FILE *fp = tor_fopen_cloexec(from_file, "r");
   int applied_lines = 0;
   time_t file_time;
   int ok;

+ 3 - 3
src/or/eventdns.c

@@ -2286,7 +2286,7 @@ _evdns_nameserver_add_impl(const struct sockaddr *address,
 
 	evtimer_set(&ns->timeout_event, nameserver_prod_callback, ns);
 
-	ns->socket = socket(PF_INET, SOCK_DGRAM, 0);
+	ns->socket = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
 	if (ns->socket < 0) { err = 1; goto out1; }
 #ifdef WIN32
 	{
@@ -3035,7 +3035,7 @@ evdns_resolv_conf_parse(int flags, const char *const filename) {
 
 	log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
 
-	fd = open(filename, O_RDONLY);
+	fd = tor_open_cloexec(filename, O_RDONLY, 0);
 	if (fd < 0) {
 		evdns_resolv_set_defaults(flags);
 		return 1;
@@ -3455,7 +3455,7 @@ main(int c, char **v) {
 	if (servertest) {
 		int sock;
 		struct sockaddr_in my_addr;
-		sock = socket(PF_INET, SOCK_DGRAM, 0);
+		sock = tor_open_socket(PF_INET, SOCK_DGRAM, 0);
 		fcntl(sock, F_SETFL, O_NONBLOCK);
 		my_addr.sin_family = AF_INET;
 		my_addr.sin_port = htons(10053);

+ 1 - 1
src/or/geoip.c

@@ -206,7 +206,7 @@ geoip_load_file(const char *filename, or_options_t *options)
   int severity = options_need_geoip_info(options, &msg) ? LOG_WARN : LOG_INFO;
   crypto_digest_env_t *geoip_digest_env = NULL;
   clear_geoip_db();
-  if (!(f = fopen(filename, "r"))) {
+  if (!(f = tor_fopen_cloexec(filename, "r"))) {
     log_fn(severity, LD_GENERAL, "Failed to open GEOIP file %s.  %s",
            filename, msg);
     return -1;