# HG changeset patch # User Timo Sirainen # Date 1189864698 -10800 # Node ID 1b21dfee7bd7e00b1ff94f63c5df62fb6bcbf152 # Parent 1622e332c8ae9b557129f8bcf09e5abfe67cfc78 Calculate needed fd count better. Make sure we have one unused fd available when exec()ing so it doesn't fail. 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 @@ 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 @@ 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,15 +684,21 @@ } 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", group->set->login_executable);