dovecot: Calculate needed fd count better. Make sure we have one...

dovecot at dovecot.org dovecot at dovecot.org
Sat Sep 15 17:02:38 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/1b21dfee7bd7
changeset: 6396:1b21dfee7bd7
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Sep 15 16:58:18 2007 +0300
description:
Calculate needed fd count better. Make sure we have one unused fd available
when exec()ing so it doesn't fail.

diffstat:

1 file changed, 14 insertions(+), 8 deletions(-)
src/master/login-process.c |   22 ++++++++++++++--------

diffs (50 lines):

diff -r 1622e332c8ae -r 1b21dfee7bd7 src/master/login-process.c
--- a/src/master/login-process.c	Sat Sep 15 16:57:11 2007 +0300
+++ b/src/master/login-process.c	Sat Sep 15 16:58:18 2007 +0300
@@ -589,8 +589,8 @@ static pid_t create_login_process(struct
 	const char *prefix;
 	pid_t pid;
 	ARRAY_TYPE(dup2) dups;
-	unsigned int i, listen_count = 0, ssl_listen_count = 0;
-	int fd[2], log_fd, cur_fd;
+	unsigned int i, fd_limit, listen_count = 0, ssl_listen_count = 0;
+	int fd[2], log_fd, cur_fd, tmp_fd;
 
 	if (group->set->login_uid == 0)
 		i_fatal("Login process must not run as root");
@@ -664,8 +664,8 @@ static pid_t create_login_process(struct
 		i_fatal("Failed to dup2() fds");
 
 	/* don't close any of these */
-	while (cur_fd >= 0)
-		fd_close_on_exec(cur_fd--, FALSE);
+	for (tmp_fd = 0; tmp_fd <= cur_fd; tmp_fd++)
+		fd_close_on_exec(tmp_fd, FALSE);
 
 	(void)close(fd[0]);
 	(void)close(fd[1]);
@@ -684,14 +684,20 @@ static pid_t create_login_process(struct
 	}
 
 	restrict_process_size(group->set->login_process_size, (unsigned int)-1);
-	if (group->set->login_process_per_connection)
-		restrict_fd_limit(16 + 2);
-	else
-		restrict_fd_limit(16 + 2*group->set->login_max_connections);
+	fd_limit = 16 + listen_count + ssl_listen_count +
+		2 * (group->set->login_process_per_connection ? 1 :
+		     group->set->login_max_connections);
+	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