changeset 727:8dd8ebe6bcac HEAD

We use close-on-exec flag now to make sure that master process closes the fds when executing other processes.
author Timo Sirainen <tss@iki.fi>
date Sun, 01 Dec 2002 17:39:20 +0200
parents d60c6c65d1ca
children 883cda17d175
files src/auth/main.c src/imap/main.c src/lib/Makefile.am src/lib/fd-close-on-exec.c src/lib/fd-close-on-exec.h src/login/main.c src/master/auth-process.c src/master/auth-process.h src/master/login-process.c src/master/login-process.h src/master/main.c
diffstat 11 files changed, 90 insertions(+), 34 deletions(-) [+]
line wrap: on
line diff
--- a/src/auth/main.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/auth/main.c	Sun Dec 01 17:39:20 2002 +0200
@@ -5,6 +5,7 @@
 #include "network.h"
 #include "lib-signals.h"
 #include "restrict-access.h"
+#include "fd-close-on-exec.h"
 #include "randgen.h"
 #include "auth.h"
 #include "cookie.h"
@@ -93,6 +94,9 @@
 
 int main(int argc __attr_unused__, char *argv[] __attr_unused__)
 {
+#ifdef DEBUG
+        fd_debug_verify_leaks(4, 1024);
+#endif
 	/* NOTE: we start rooted, so keep the code minimal until
 	   restrict_access_by_env() is called */
 	lib_init();
--- a/src/imap/main.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/imap/main.c	Sun Dec 01 17:39:20 2002 +0200
@@ -5,6 +5,7 @@
 #include "lib-signals.h"
 #include "rawlog.h"
 #include "restrict-access.h"
+#include "fd-close-on-exec.h"
 
 #include <stdlib.h>
 #include <syslog.h>
@@ -104,6 +105,9 @@
 
 int main(int argc, char *argv[])
 {
+#ifdef DEBUG
+        fd_debug_verify_leaks(3, 1024);
+#endif
 	/* NOTE: we start rooted, so keep the code minimal until
 	   restrict_access_by_env() is called */
 	lib_init();
--- a/src/lib/Makefile.am	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/lib/Makefile.am	Sun Dec 01 17:39:20 2002 +0200
@@ -7,6 +7,7 @@
 	data-stack.c \
 	env-util.c \
 	failures.c \
+	fd-close-on-exec.c \
 	fdpass.c \
 	file-lock.c \
 	file-set-size.c \
@@ -54,6 +55,7 @@
 	data-stack.h \
 	env-util.h \
 	failures.h \
+	fd-close-on-exec.h \
 	fdpass.h \
 	file-lock.h \
 	file-set-size.h \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/fd-close-on-exec.c	Sun Dec 01 17:39:20 2002 +0200
@@ -0,0 +1,50 @@
+/*
+    Copyright (c) 2002 Timo Sirainen
+
+    Permission is hereby granted, free of charge, to any person obtaining
+    a copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+*/
+
+#include "lib.h"
+#include "fd-close-on-exec.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+void fd_close_on_exec(int fd, int set)
+{
+	int flags;
+
+	flags = fcntl(fd, F_GETFD, 0);
+	if (flags < 0)
+		i_fatal("fcntl(F_GETFD) failed: %m");
+
+	flags = set ? (flags | FD_CLOEXEC) : (flags & ~FD_CLOEXEC);
+	if (fcntl(fd, F_SETFD, flags) < 0)
+		i_fatal("fcntl(F_SETFD) failed: %m");
+}
+
+void fd_debug_verify_leaks(int first_fd, int last_fd)
+{
+	while (first_fd < last_fd) {
+		if (fcntl(first_fd, F_GETFD, 0) != -1 || errno != EBADF)
+			i_fatal("Leaked file descriptor: %d", first_fd);
+		first_fd++;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib/fd-close-on-exec.h	Sun Dec 01 17:39:20 2002 +0200
@@ -0,0 +1,10 @@
+#ifndef __FD_CLOSE_ON_EXEC_H
+#define __FD_CLOSE_ON_EXEC_H
+
+/* Change close-on-exec flag of fd. */
+void fd_close_on_exec(int fd, int set);
+
+/* Verify that fds in given range don't exist. */
+void fd_debug_verify_leaks(int first_fd, int last_fd);
+
+#endif
--- a/src/login/main.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/login/main.c	Sun Dec 01 17:39:20 2002 +0200
@@ -4,6 +4,7 @@
 #include "ioloop.h"
 #include "lib-signals.h"
 #include "restrict-access.h"
+#include "fd-close-on-exec.h"
 #include "auth-connection.h"
 #include "master.h"
 #include "client.h"
@@ -192,6 +193,9 @@
 
 int main(int argc __attr_unused__, char *argv[] __attr_unused__)
 {
+#ifdef DEBUG
+        fd_debug_verify_leaks(3, 1024);
+#endif
 	/* NOTE: we start rooted, so keep the code minimal until
 	   restrict_access_by_env() is called */
 	lib_init();
--- a/src/master/auth-process.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/master/auth-process.c	Sun Dec 01 17:39:20 2002 +0200
@@ -3,6 +3,7 @@
 #include "common.h"
 #include "ioloop.h"
 #include "env-util.h"
+#include "fd-close-on-exec.h"
 #include "network.h"
 #include "obuffer.h"
 #include "restrict-access.h"
@@ -171,13 +172,12 @@
 	const char *path;
 	struct passwd *pwd;
 	pid_t pid;
-	int fd[2], listen_fd;
+	int fd[2], listen_fd, i;
 
 	if ((pwd = getpwnam(config->user)) == NULL)
 		i_fatal("Auth user doesn't exist: %s", config->user);
 
-	/* create communication to process with a socket pair
-	   FIXME: pipe() would work as well, would it be better? */
+	/* create communication to process with a socket pair */
 	if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) == -1) {
 		i_error("socketpair() failed: %m");
 		return -1;
@@ -193,6 +193,7 @@
 
 	if (pid != 0) {
 		/* master */
+		fd_close_on_exec(fd[0], TRUE);
 		auth_process_new(pid, fd[0], config->name);
 		(void)close(fd[1]);
 		return pid;
@@ -235,6 +236,9 @@
 		(void)close(listen_fd);
 	}
 
+	for (i = 0; i <= 2; i++)
+		fd_close_on_exec(i, FALSE);
+
 	/* setup access environment - needs to be done after
 	   clean_child_process() since it clears environment */
 	restrict_access_set_env(config->user, pwd->pw_uid, pwd->pw_gid,
@@ -300,14 +304,6 @@
 	return count;
 }
 
-void auth_processes_cleanup(void)
-{
-	AuthProcess *p;
-
-	for (p = processes; p != NULL; p = p->next)
-		(void)close(p->fd);
-}
-
 void auth_processes_destroy_all(void)
 {
 	AuthProcess *next;
--- a/src/master/auth-process.h	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/master/auth-process.h	Sun Dec 01 17:39:20 2002 +0200
@@ -16,7 +16,6 @@
 			  AuthCallback callback, void *context);
 
 /* Close any fds used by auth processes */
-void auth_processes_cleanup(void);
 void auth_processes_destroy_all(void);
 
 void auth_processes_init(void);
--- a/src/master/login-process.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/master/login-process.c	Sun Dec 01 17:39:20 2002 +0200
@@ -5,6 +5,7 @@
 #include "network.h"
 #include "obuffer.h"
 #include "fdpass.h"
+#include "fd-close-on-exec.h"
 #include "env-util.h"
 #include "restrict-access.h"
 #include "restrict-process-size.h"
@@ -266,6 +267,7 @@
 
 	if (pid != 0) {
 		/* master */
+		fd_close_on_exec(fd[0], TRUE);
 		login_process_new(pid, fd[0]);
 		(void)close(fd[1]);
 		return pid;
@@ -274,14 +276,17 @@
 	/* move communication handle */
 	if (dup2(fd[1], LOGIN_MASTER_SOCKET_FD) < 0)
 		i_fatal("login: dup2() failed: %m");
+	fd_close_on_exec(LOGIN_MASTER_SOCKET_FD, FALSE);
 
 	/* move the listen handle */
 	if (dup2(imap_fd, LOGIN_IMAP_LISTEN_FD) < 0)
 		i_fatal("login: dup2() failed: %m");
+	fd_close_on_exec(LOGIN_IMAP_LISTEN_FD, FALSE);
 
 	/* move the SSL listen handle */
 	if (dup2(imaps_fd, LOGIN_IMAPS_LISTEN_FD) < 0)
 		i_fatal("login: dup2() failed: %m");
+	fd_close_on_exec(LOGIN_IMAPS_LISTEN_FD, FALSE);
 
 	/* imap_fd and imaps_fd are closed by clean_child_process() */
 
@@ -340,19 +345,6 @@
 	wanted_processes_count = 0;
 }
 
-static void login_hash_cleanup(void *key __attr_unused__, void *value,
-			       void *context __attr_unused__)
-{
-	LoginProcess *p = value;
-
-	(void)close(p->fd);
-}
-
-void login_processes_cleanup(void)
-{
-	hash_foreach(processes, login_hash_cleanup, NULL);
-}
-
 static void login_hash_destroy(void *key __attr_unused__, void *value,
 			       void *context __attr_unused__)
 {
--- a/src/master/login-process.h	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/master/login-process.h	Sun Dec 01 17:39:20 2002 +0200
@@ -2,7 +2,6 @@
 #define __CHILD_LOGIN_H
 
 void login_process_abormal_exit(pid_t pid);
-void login_processes_cleanup(void);
 void login_processes_destroy_all(void);
 
 void login_processes_init(void);
--- a/src/master/main.c	Sun Dec 01 17:37:19 2002 +0200
+++ b/src/master/main.c	Sun Dec 01 17:39:20 2002 +0200
@@ -5,6 +5,7 @@
 #include "lib-signals.h"
 #include "network.h"
 #include "env-util.h"
+#include "fd-close-on-exec.h"
 
 #include "auth-process.h"
 #include "login-process.h"
@@ -56,14 +57,6 @@
 	if (set_log_timestamp != NULL)
 		env_put(t_strconcat("IMAP_LOGSTAMP=", set_log_timestamp, NULL));
 
-	(void)close(null_fd);
-	(void)close(imap_fd);
-	(void)close(imaps_fd);
-
-	/* close fds for auth/login processes */
-	login_processes_cleanup();
-        auth_processes_cleanup();
-
 	closelog();
 }
 
@@ -156,11 +149,13 @@
 	null_fd = open("/dev/null", O_RDONLY);
 	if (null_fd == -1)
 		i_fatal("Can't open /dev/null: %m");
+	fd_close_on_exec(null_fd, TRUE);
 
 	imap_fd = set_imap_port == 0 ? dup(null_fd) :
 		net_listen(imap_ip, &set_imap_port);
 	if (imap_fd == -1)
 		i_fatal("listen(%d) failed: %m", set_imap_port);
+	fd_close_on_exec(imap_fd, TRUE);
 
 #ifdef HAVE_SSL
 	imaps_fd = set_ssl_cert_file == NULL || *set_ssl_cert_file == '\0' ||
@@ -172,6 +167,7 @@
 #endif
 	if (imaps_fd == -1)
 		i_fatal("listen(%d) failed: %m", set_imaps_port);
+	fd_close_on_exec(imaps_fd, TRUE);
 }
 
 static void main_init(void)