dovecot-1.1: Change fd limit in login process after it's execed....

dovecot at dovecot.org dovecot at dovecot.org
Fri Jun 13 00:49:02 EEST 2008


details:   http://hg.dovecot.org/dovecot-1.1/rev/bc3eab510b2b
changeset: 7652:bc3eab510b2b
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Jun 13 00:48:58 2008 +0300
description:
Change fd limit in login process after it's execed. This fixes OSes which
don't allow setting fd limit below what's already used (e.g. HP-UX).

diffstat:

2 files changed, 20 insertions(+), 31 deletions(-)
src/login-common/main.c    |   35 +++++++++++++++++++----------------
src/master/login-process.c |   16 +---------------

diffs (111 lines):

diff -r 5e1a0c976545 -r bc3eab510b2b src/login-common/main.c
--- a/src/login-common/main.c	Fri Jun 13 00:36:23 2008 +0300
+++ b/src/login-common/main.c	Fri Jun 13 00:48:58 2008 +0300
@@ -250,21 +250,21 @@ static void auth_connect_notify(struct a
 
 static void drop_privileges(void)
 {
-	const char *env;
+	const char *value;
 
 	if (!is_inetd)
 		i_set_failure_internal();
 	else {
 		/* log to syslog */
-		env = getenv("SYSLOG_FACILITY");
+		value = getenv("SYSLOG_FACILITY");
 		i_set_failure_syslog(process_name, LOG_NDELAY,
-				     env == NULL ? LOG_MAIL : atoi(env));
+				     value == NULL ? LOG_MAIL : atoi(value));
 
 		/* if we don't chroot, we must chdir */
-		env = getenv("LOGIN_DIR");
-		if (env != NULL) {
-			if (chdir(env) < 0)
-				i_error("chdir(%s) failed: %m", env);
+		value = getenv("LOGIN_DIR");
+		if (value != NULL) {
+			if (chdir(value) < 0)
+				i_error("chdir(%s) failed: %m", value);
 		}
 	}
 
@@ -272,6 +272,18 @@ static void drop_privileges(void)
 	   key file. */
 	random_init();
 	ssl_proxy_init();
+
+	value = getenv("LISTEN_FDS");
+	listen_count = value == NULL ? 0 : atoi(value);
+	value = getenv("SSL_LISTEN_FDS");
+	ssl_listen_count = value == NULL ? 0 : atoi(value);
+	value = getenv("MAX_CONNECTIONS");
+	max_connections = value == NULL ? 1 : strtoul(value, NULL, 10);
+
+	/* set the number of fds we want to use. it may get increased or
+	   decreased. leave a couple of extra fds for auth sockets and such */
+	restrict_fd_limit(LOGIN_MASTER_SOCKET_FD + 16 +
+			  listen_count + ssl_listen_count + max_connections);
 
 	/* Refuse to run as root - we should never need it and it's
 	   dangerous with SSL. */
@@ -302,9 +314,6 @@ static void main_init(void)
 	verbose_proctitle = getenv("VERBOSE_PROCTITLE") != NULL;
         verbose_ssl = getenv("VERBOSE_SSL") != NULL;
         verbose_auth = getenv("VERBOSE_AUTH") != NULL;
-
-	value = getenv("MAX_CONNECTIONS");
-	max_connections = value == NULL ? 1 : strtoul(value, NULL, 10);
 
 	greeting = getenv("GREETING");
 	if (greeting == NULL)
@@ -338,12 +347,6 @@ static void main_init(void)
 	auth_client = auth_client_new(login_process_uid);
         auth_client_set_connect_notify(auth_client, auth_connect_notify, NULL);
 	clients_init();
-
-	value = getenv("LISTEN_FDS");
-	listen_count = value == NULL ? 0 : atoi(value);
-
-	value = getenv("SSL_LISTEN_FDS");
-	ssl_listen_count = value == NULL ? 0 : atoi(value);
 
 	if (!ssl_initialized && ssl_listen_count > 0) {
 		/* this shouldn't happen, master should have
diff -r 5e1a0c976545 -r bc3eab510b2b src/master/login-process.c
--- a/src/master/login-process.c	Fri Jun 13 00:36:23 2008 +0300
+++ b/src/master/login-process.c	Fri Jun 13 00:48:58 2008 +0300
@@ -590,7 +590,7 @@ static pid_t create_login_process(struct
 	const char *prefix;
 	pid_t pid;
 	ARRAY_TYPE(dup2) dups;
-	unsigned int i, fd_limit, listen_count = 0, ssl_listen_count = 0;
+	unsigned int i, listen_count = 0, ssl_listen_count = 0;
 	int fd[2], log_fd, cur_fd, tmp_fd;
 
 	if (group->set->login_uid == 0)
@@ -686,24 +686,10 @@ static pid_t create_login_process(struct
 	}
 
 	restrict_process_size(group->set->login_process_size, (unsigned int)-1);
-	/* +16 is just for some extra things the process might want */
-	fd_limit = 16 + cur_fd +
-		2 * (group->set->login_process_per_connection ? 1 :
-		     group->set->login_max_connections);
-#ifdef DEBUG
-	if (!gdb)
-#endif
-		restrict_fd_limit(fd_limit);
 
 	/* make sure we don't leak syslog fd, but do it last so that
 	   any errors above will be logged */
 	closelog();
-
-	/* execv() needs at least one file descriptor. we might have all fds
-	   up to fd_limit used already, so close one we don't care about.
-	   either it succeeds or fails with EBADF, doesn't matter. */
-	i_assert(fd_limit > (unsigned int)cur_fd+1);
-	(void)close(cur_fd+1);
 
 	client_process_exec(group->set->login_executable, "");
 	i_fatal_status(FATAL_EXEC, "execv(%s) failed: %m",


More information about the dovecot-cvs mailing list