service-process.c revision 5f5870385cff47efd2f58e7892f251cf13761528
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "common.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "array.h"
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#include "aqueue.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "ioloop.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "istream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "ostream.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "write-full.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "base64.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "hash.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "str.h"
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen#include "strescape.h"
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen#include "llist.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "hostpid.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "env-util.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "fd-close-on-exec.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "restrict-access.h"
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen#include "restrict-process-size.h"
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen#include "eacces-error.h"
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen#include "master-service.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "master-service-settings.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "dup2-array.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "service.h"
cf2e6953d03a1c22f272ec19432fc03c136ac1bbTimo Sirainen#include "service-anvil.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "service-log.h"
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen#include "service-process-notify.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "service-process.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <stdlib.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <unistd.h>
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen#include <fcntl.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <syslog.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <signal.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <sys/wait.h>
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainenstatic void
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenservice_dup_fds(struct service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct service_listener *const *listeners;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ARRAY_TYPE(dup2) dups;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen string_t *listener_names;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen int fd = MASTER_LISTEN_FD_FIRST;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen unsigned int i, count, socket_listener_count, ssl_socket_count;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* stdin/stdout is already redirected to /dev/null. Other master fds
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen should have been opened with fd_close_on_exec() so we don't have to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen worry about them.
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen because the destination fd might be another one's source fd we have
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen to be careful not to overwrite anything. dup() the fd when needed */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen socket_listener_count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen listeners = array_get(&service->listeners, &count);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen t_array_init(&dups, count + 10);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen listener_names = t_str_new(256);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen switch (service->type) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen case SERVICE_TYPE_LOG:
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen i_assert(fd == MASTER_LISTEN_FD_FIRST);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen services_log_dup2(&dups, service->list, fd,
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen &socket_listener_count);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen fd += socket_listener_count;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen break;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen case SERVICE_TYPE_ANVIL:
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen dup2_append(&dups, service_anvil_global->log_fdpass_fd[0],
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen MASTER_ANVIL_LOG_FDPASS_FD);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* nonblocking anvil fd must be the first one. anvil treats it
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen as the master's fd */
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen dup2_append(&dups, service_anvil_global->nonblocking_fd[0], fd++);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen dup2_append(&dups, service_anvil_global->blocking_fd[0], fd++);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen socket_listener_count += 2;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen break;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen default:
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen break;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen /* anvil/log fds have no names */
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen for (i = MASTER_LISTEN_FD_FIRST; i < (unsigned int)fd; i++)
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str_append_c(listener_names, '\t');
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen /* first add non-ssl listeners */
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen for (i = 0; i < count; i++) {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (listeners[i]->fd != -1 &&
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen (listeners[i]->type != SERVICE_LISTENER_INET ||
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen !listeners[i]->set.inetset.set->ssl)) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str_tabescape_write(listener_names, listeners[i]->name);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str_append_c(listener_names, '\t');
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen dup2_append(&dups, listeners[i]->fd, fd++);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen socket_listener_count++;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen /* then ssl-listeners */
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen ssl_socket_count = 0;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen for (i = 0; i < count; i++) {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (listeners[i]->fd != -1 &&
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen listeners[i]->type == SERVICE_LISTENER_INET &&
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen listeners[i]->set.inetset.set->ssl) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str_tabescape_write(listener_names, listeners[i]->name);
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str_append_c(listener_names, '\t');
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen dup2_append(&dups, listeners[i]->fd, fd++);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen socket_listener_count++;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen ssl_socket_count++;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (service->login_notify_fd != -1) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen dup2_append(&dups, service->login_notify_fd,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen MASTER_LOGIN_NOTIFY_FD);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen switch (service->type) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen case SERVICE_TYPE_LOG:
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen case SERVICE_TYPE_ANVIL:
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen case SERVICE_TYPE_CONFIG:
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen dup2_append(&dups, null_fd, MASTER_ANVIL_FD);
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen break;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen case SERVICE_TYPE_UNKNOWN:
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen case SERVICE_TYPE_LOGIN:
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen case SERVICE_TYPE_STARTUP:
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen dup2_append(&dups, service_anvil_global->blocking_fd[1],
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen MASTER_ANVIL_FD);
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen break;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen dup2_append(&dups, service->status_fd[1], MASTER_STATUS_FD);
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen if (service->type != SERVICE_TYPE_ANVIL) {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen dup2_append(&dups, service->list->master_dead_pipe_fd[1],
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen MASTER_DEAD_FD);
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen } else {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen dup2_append(&dups, global_master_dead_pipe_fd[1],
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen MASTER_DEAD_FD);
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen if (service->type == SERVICE_TYPE_LOG) {
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen /* keep stderr as-is. this is especially important when
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen log_path=/dev/stderr, but might be helpful even in other
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen situations for logging startup errors */
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* set log file to stderr. dup2() here immediately so that
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen we can set up logging to it without causing any log messages
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen to be lost. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->log_fd[1] != -1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put("LOG_SERVICE=1");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (dup2(service->log_fd[1], STDERR_FILENO) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_fatal("dup2(log fd) failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_set_failure_internal();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* make sure we don't leak syslog fd. try to do it as late as possible,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen but also before dup2()s in case syslog fd is one of them. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen closelog();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (dup2_array(&dups) < 0)
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen i_fatal("service(%s): dup2s failed", service->set->name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen i_assert(fd == MASTER_LISTEN_FD_FIRST + (int)socket_listener_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strdup_printf("SOCKET_COUNT=%d", socket_listener_count));
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen env_put(t_strdup_printf("SSL_SOCKET_COUNT=%d", ssl_socket_count));
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen env_put(t_strdup_printf("SOCKET_NAMES=%s", str_c(listener_names)));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainenstatic void
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainendrop_privileges(struct service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct restrict_access_settings rset;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen bool disallow_root;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen unsigned int len;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen if (service->vsz_limit != 0)
9ebd0c59de5f8240c0dbc58773fe5679391199dbTimo Sirainen restrict_process_size(service->vsz_limit);
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen restrict_access_init(&rset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.uid = service->uid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.gid = service->gid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.privileged_gid = service->privileged_gid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.chroot_dir = *service->set->chroot == '\0' ? NULL :
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->set->chroot;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen if (rset.chroot_dir != NULL) {
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen /* drop trailing / if it exists */
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen len = strlen(rset.chroot_dir);
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen if (rset.chroot_dir[len-1] == '/')
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen rset.chroot_dir = t_strndup(rset.chroot_dir, len-1);
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rset.extra_groups = service->extra_gids;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4b2a1030f9b51e90f6ff4cdbc115871a398c1e0fTimo Sirainen restrict_access_set_env(&rset);
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen if (service->set->drop_priv_before_exec) {
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen disallow_root = service->type == SERVICE_TYPE_LOGIN;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen restrict_access(&rset, NULL, disallow_root);
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainenstatic void service_process_setup_config_environment(struct service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen const struct master_service_settings *set = service->list->service_set;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen switch (service->type) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case SERVICE_TYPE_CONFIG:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->config_file_path, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case SERVICE_TYPE_LOG:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* give the log's configuration directly, so it won't depend
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen on config process */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put("DOVECONF_ENV=1");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat("LOG_PATH=", set->log_path, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat("INFO_LOG_PATH=", set->info_log_path, NULL));
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen env_put(t_strconcat("DEBUG_LOG_PATH=", set->debug_log_path, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat("LOG_TIMESTAMP=", set->log_timestamp, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat("SYSLOG_FACILITY=", set->syslog_facility, NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen default:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strconcat(MASTER_CONFIG_FILE_ENV"=",
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen services_get_config_socket_path(service->list), NULL));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen}
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainenstatic void
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainenservice_process_setup_environment(struct service *service, unsigned int uid)
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen{
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen master_service_env_clean();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d482079eb385cd071bbc9637cacee225e4aff968Timo Sirainen env_put(MASTER_IS_PARENT_ENV"=1");
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen service_process_setup_config_environment(service);
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen env_put(t_strdup_printf(MASTER_CLIENT_LIMIT_ENV"=%u",
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen service->client_limit));
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen env_put(t_strdup_printf(MASTER_PROCESS_LIMIT_ENV"=%u",
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen service->process_limit));
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen env_put(t_strdup_printf(MASTER_SERVICE_IDLE_KILL_ENV"=%u",
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen service->idle_kill));
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen if (service->set->service_count != 0) {
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen env_put(t_strdup_printf(MASTER_SERVICE_COUNT_ENV"=%u",
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen service->set->service_count));
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(t_strdup_printf(MASTER_UID_ENV"=%u", uid));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!service->set->master_set->version_ignore)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen env_put(MASTER_DOVECOT_VERSION_ENV"="PACKAGE_VERSION);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen
0547a828ee9647fc5fd2e359b145774740a697feTimo Sirainen if (ssl_manual_key_password != NULL && service->have_inet_listeners) {
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen /* manually given SSL password. give it only to services
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen that have inet listeners. */
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen env_put(t_strconcat(MASTER_SSL_KEY_PASSWORD_ENV"=",
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen ssl_manual_key_password, NULL));
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen }
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen if (service->type == SERVICE_TYPE_ANVIL &&
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen service_anvil_global->restarted)
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen env_put("ANVIL_RESTARTED=1");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void service_process_status_timeout(struct service_process *process)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen service_error(process->service,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen "Initial status notification not received in %d "
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen "seconds, killing the process",
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen SERVICE_FIRST_STATUS_TIMEOUT_SECS);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (kill(process->pid, SIGKILL) < 0 && errno != ESRCH) {
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen service_error(process->service, "kill(%s, SIGKILL) failed: %m",
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen dec2str(process->pid));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timeout_remove(&process->to_status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainenstruct service_process *service_process_create(struct service *service)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen static unsigned int uid_counter = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct service_process *process;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int uid = ++uid_counter;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pid_t pid;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen bool process_forked;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen i_assert(service->status_fd[0] != -1);
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen if (service->to_throttle != NULL) {
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen /* throttling service, don't create new processes */
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen return NULL;
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen }
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen if (service->list->destroying) {
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen /* these services are being destroyed, no point in creating
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen new processes now */
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen return NULL;
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (service->type == SERVICE_TYPE_ANVIL &&
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen service_anvil_global->pid != 0) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen pid = service_anvil_global->pid;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen uid = service_anvil_global->uid;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen process_forked = FALSE;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen } else {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen pid = fork();
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen process_forked = TRUE;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (pid < 0) {
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen service_error(service, "fork() failed: %m");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (pid == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* child */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_process_setup_environment(service, uid);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service_dup_fds(service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen drop_privileges(service);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen process_exec(service->executable, NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen process = i_new(struct service_process, 1);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen process->service = service;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process->refcount = 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process->pid = pid;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process->uid = uid;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (process_forked) {
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen process->to_status =
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen timeout_add(SERVICE_FIRST_STATUS_TIMEOUT_SECS * 1000,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen service_process_status_timeout, process);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen process->available_count = service->client_limit;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->process_count++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->process_avail++;
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen DLLIST_PREPEND(&service->processes, process);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen service_list_ref(service->list);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen hash_table_insert(service_pids, &process->pid, process);
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen if (service->type == SERVICE_TYPE_ANVIL && process_forked)
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen service_anvil_process_created(process);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return process;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid service_process_destroy(struct service_process *process)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct service *service = process->service;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen struct service_list *service_list = service->list;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen DLLIST_REMOVE(&service->processes, process);
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen hash_table_remove(service_pids, &process->pid);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (process->available_count > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->process_avail--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service->process_count--;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(service->process_avail <= service->process_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (process->to_status != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen timeout_remove(&process->to_status);
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen if (process->to_idle != NULL)
d8552f9f65e5ff64be5de9faf9a8171799a0bbecTimo Sirainen timeout_remove(&process->to_idle);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (service->list->log_byes != NULL)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen service_process_notify_add(service->list->log_byes, process);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process->destroyed = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen service_process_unref(process);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen if (service->process_count < service->process_limit &&
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service->type == SERVICE_TYPE_LOGIN)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen service_login_notify(service, FALSE);
6fdfa4d4cf14d1d7764d7faa8258f112e39c8dbeTimo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen service_list_unref(service_list);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid service_process_ref(struct service_process *process)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(process->refcount > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen process->refcount++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint service_process_unref(struct service_process *process)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(process->refcount > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (--process->refcount > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(process->destroyed);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_free(process);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic const char *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenget_exit_status_message(struct service *service, enum fatal_exit_status status)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen switch (status) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_LOGOPEN:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "Can't open log file";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_LOGWRITE:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "Can't write to log file";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_LOGERROR:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "Internal logging error";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_OUTOFMEM:
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen if (service->vsz_limit == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "Out of memory";
19d01d72f98e7f28a1d8aed146adb6a777158092Timo Sirainen return t_strdup_printf("Out of memory (service %s { vsz_limit=%u MB }, "
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen "you may need to increase it)",
19d01d72f98e7f28a1d8aed146adb6a777158092Timo Sirainen service->set->name,
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen (unsigned int)(service->vsz_limit/1024/1024));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_EXEC:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "exec() failed";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen case FATAL_DEFAULT:
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return "Fatal failure";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
129db31de1780783a175633eba5811e44c361a81Timo Sirainenstatic void
129db31de1780783a175633eba5811e44c361a81Timo Sirainenlog_coredump(struct service *service, string_t *str, int status)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#ifdef WCOREDUMP
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int signum = WTERMSIG(status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (WCOREDUMP(status)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append(str, " (core dumped)");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (signum != SIGABRT && signum != SIGSEGV && signum != SIGBUS)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* let's try to figure out why we didn't get a core dump */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (core_dumps_disabled) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_printfa(str, " (core dumps disabled)");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen#ifndef HAVE_PR_SET_DUMPABLE
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen if (!service->set->drop_priv_before_exec && service->uid != 0) {
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen str_printfa(str, " (core not dumped - set service %s "
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen "{ drop_priv_before_exec=yes })",
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen service->set->name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
114162093a3eb36c23a4ce4d4f2a43541dc18cc2Timo Sirainen if (*service->set->privileged_group != '\0' && service->uid != 0) {
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen str_printfa(str, " (core not dumped - service %s "
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen "{ privileged_group } prevented it)",
ca502ca792708238ac2c23481c3bf94eda1f743fTimo Sirainen service->set->name);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen#else
129db31de1780783a175633eba5811e44c361a81Timo Sirainen if (!service->set->login_dump_core &&
129db31de1780783a175633eba5811e44c361a81Timo Sirainen service->type == SERVICE_TYPE_LOGIN) {
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen str_printfa(str, " (core not dumped - add -D parameter to "
dfcc56dc6c485fe45a3fa18325f047bfaae65019Timo Sirainen "service %s { executable }", service->set->name);
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen return;
63849db64682675a2fd3e1aea05c10ecbc6d473aTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#endif
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append(str, " (core not dumped)");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#endif
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenservice_process_get_status_error(string_t *str, struct service_process *process,
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen int status, bool *default_fatal_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct service *service = process->service;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *msg;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen *default_fatal_r = FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen str_printfa(str, "service(%s): child %s ", service->set->name,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen dec2str(process->pid));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (WIFSIGNALED(status)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_printfa(str, "killed with signal %d", WTERMSIG(status));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen log_coredump(service, str, status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (!WIFEXITED(status)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_printfa(str, "died with status %d", status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen status = WEXITSTATUS(status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (status == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_truncate(str, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_printfa(str, "returned error %d", status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen msg = get_exit_status_message(service, status);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (msg != NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_printfa(str, " (%s)", msg);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (status == FATAL_DEFAULT)
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen *default_fatal_r = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void service_process_log(struct service_process *process,
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen bool default_fatal, const char *str)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *data;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen if (process->service->log_fd[1] == -1) {
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen i_error("%s", str);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* log it via the log process in charge of handling
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen this process's logging */
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen data = t_strdup_printf("%d %s %s %s\n",
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen process->service->log_process_internal_fd,
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen dec2str(process->pid),
800fc30be46bc6f8380f6de04aea7c19ea839ddfTimo Sirainen default_fatal ? "DEFAULT-FATAL" : "FATAL", str);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (write(process->service->list->master_log_fd[1],
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen data, strlen(data)) < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_error("write(log process) failed: %m");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen i_error("%s", str);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid service_process_log_status_error(struct service_process *process,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int status)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* fast path */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen T_BEGIN {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen string_t *str = t_str_new(256);
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen bool default_fatal;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen service_process_get_status_error(str, process, status,
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen &default_fatal);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (str_len(str) > 0)
9c8f854d95d8d895022a75f140a0a500eb200d39Timo Sirainen service_process_log(process, default_fatal, str_c(str));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } T_END;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}