From: Timo Sirainen Date: Thu, 12 Jun 2008 21:48:58 +0000 (+0300) Subject: Change fd limit in login process after it's execed. This fixes OSes which X-Git-Tag: 1.2.alpha1~309 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2e9a0c3a4404684d0089403e54665121ce7da655;p=thirdparty%2Fdovecot%2Fcore.git 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). --HG-- branch : HEAD --- diff --git a/src/login-common/main.c b/src/login-common/main.c index 80cb127880..42778073c8 100644 --- a/src/login-common/main.c +++ b/src/login-common/main.c @@ -250,21 +250,21 @@ static void auth_connect_notify(struct auth_client *client ATTR_UNUSED, 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); } } @@ -273,6 +273,18 @@ static void drop_privileges(void) 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. */ restrict_access_by_env(TRUE); @@ -303,9 +315,6 @@ static void main_init(void) 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) greeting = PACKAGE" ready."; @@ -339,12 +348,6 @@ static void main_init(void) 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 disabled the ssl socket.. */ diff --git a/src/master/login-process.c b/src/master/login-process.c index 8c2c207c5c..7e5c422af3 100644 --- a/src/master/login-process.c +++ b/src/master/login-process.c @@ -590,7 +590,7 @@ static pid_t create_login_process(struct login_group *group) 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,25 +686,11 @@ static pid_t create_login_process(struct login_group *group) } 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", group->set->login_executable);