X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/ef8a2428cfe2ba86715e8dc1f966f9532ff5d190..a85c067ba6c6940512cf57ec213277a370d87e70:/src/src/daemon.c diff --git a/src/src/daemon.c b/src/src/daemon.c index 4a3cb6adb..0afc7ca86 100644 --- a/src/src/daemon.c +++ b/src/src/daemon.c @@ -2,9 +2,10 @@ * Exim - an Internet mail transport agent * *************************************************/ +/* Copyright (c) The Exim Maintainers 2020 - 2022 */ /* Copyright (c) University of Cambridge 1995 - 2018 */ -/* Copyright (c) The Exim Maintainers 2020 - 2021 */ /* See the file NOTICE for conditions of use and distribution. */ +/* SPDX-License-Identifier: GPL-2.0-only */ /* Functions concerned with running Exim as a daemon */ @@ -1132,13 +1133,43 @@ exim_exit(EXIT_SUCCESS); * Listener socket for local work prompts * *************************************************/ +ssize_t +daemon_client_sockname(struct sockaddr_un * sup, uschar ** sname) +{ +#ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS +sup->sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */ +return offsetof(struct sockaddr_un, sun_path) + 1 + + snprintf(sup->sun_path+1, sizeof(sup->sun_path)-1, "exim_%d", getpid()); +#else +*sname = string_sprintf("%s/p_%d", spool_directory, getpid()); +return offsetof(struct sockaddr_un, sun_path) + + snprintf(sup->sun_path, sizeof(sup->sun_path), "%s", sname); +#endif +} + +ssize_t +daemon_notifier_sockname(struct sockaddr_un * sup) +{ +#ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS +sup->sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */ +return offsetof(struct sockaddr_un, sun_path) + 1 + + snprintf(sup->sun_path+1, sizeof(sup->sun_path)-1, "%s", + expand_string(notifier_socket)); +#else +return offsetof(struct sockaddr_un, sun_path) + + snprintf(sup->sun_path, sizeof(sup->sun_path), "%s", + expand_string(notifier_socket)); +#endif +} + + static void daemon_notifier_socket(void) { int fd; const uschar * where; struct sockaddr_un sa_un = {.sun_family = AF_UNIX}; -int len; +ssize_t len; if (!notifier_socket || !*notifier_socket) { @@ -1163,20 +1194,15 @@ if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) (void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); #endif +len = daemon_notifier_sockname(&sa_un); + #ifdef EXIM_HAVE_ABSTRACT_UNIX_SOCKETS -sa_un.sun_path[0] = 0; /* Abstract local socket addr - Linux-specific? */ -len = offsetof(struct sockaddr_un, sun_path) + 1 - + snprintf(sa_un.sun_path+1, sizeof(sa_un.sun_path)-1, "%s", - expand_string(notifier_socket)); DEBUG(D_any) debug_printf(" @%s\n", sa_un.sun_path+1); #else /* filesystem-visible and persistent; will neeed removal */ -len = offsetof(struct sockaddr_un, sun_path) - + snprintf(sa_un.sun_path, sizeof(sa_un.sun_path), "%s", - expand_string(notifier_socket)); DEBUG(D_any) debug_printf(" %s\n", sa_un.sun_path); #endif -if (bind(fd, (const struct sockaddr *)&sa_un, len) < 0) +if (bind(fd, (const struct sockaddr *)&sa_un, (socklen_t)len) < 0) { where = US"bind"; goto bad; } #ifdef SO_PASSCRED /* Linux */ @@ -1205,7 +1231,11 @@ bad: static uschar queuerun_msgid[MESSAGE_ID_LENGTH+1]; -/* Return TRUE if a sigalrm should be emulated */ +/* The notifier socket has something to read. Pull the message from it, decode +and do the action. + +Return TRUE if a sigalrm should be emulated */ + static BOOL daemon_notification(void) { @@ -1255,7 +1285,6 @@ for (struct cmsghdr * cp = CMSG_FIRSTHDR(&msg); { DEBUG(D_queue_run) debug_printf("%s: sender creds pid %d uid %d gid %d\n", __FUNCTION__, (int)cr->pid, (int)cr->uid, (int)cr->gid); - return FALSE; } # elif defined(LOCAL_CREDS) /* BSD-ish */ struct sockcred * cr = (struct sockcred *) CMSG_DATA(cp); @@ -1263,7 +1292,6 @@ for (struct cmsghdr * cp = CMSG_FIRSTHDR(&msg); { DEBUG(D_queue_run) debug_printf("%s: sender creds pid ??? uid %d gid %d\n", __FUNCTION__, (int)cr->sc_uid, (int)cr->sc_gid); - return FALSE; } # endif break; @@ -1294,15 +1322,18 @@ switch (buf[0]) (const struct sockaddr *)&sa_un, msg.msg_namelen) < 0) log_write(0, LOG_MAIN|LOG_PANIC, "%s: sendto: %s\n", __FUNCTION__, strerror(errno)); - return FALSE; + break; } + + case NOTIFY_REGEX: + regex_at_daemon(buf); + break; } return FALSE; } - /************************************************* * Exim Daemon Mainline * *************************************************/ @@ -1346,7 +1377,7 @@ DEBUG(D_any|D_v) debug_selector |= D_pid; /* Allocate enough pollstructs for inetd mode plus the ancillary sockets; also used when there are no listen sockets. */ -fd_polls = store_get(sizeof(struct pollfd) * 3, FALSE); +fd_polls = store_get(sizeof(struct pollfd) * 3, GET_UNTAINTED); if (f.inetd_wait_mode) { @@ -1534,7 +1565,7 @@ if (f.daemon_listen && !f.inetd_wait_mode) sep = 0; while ((s = string_nextinlist(&list, &sep, NULL, 0))) pct++; - default_smtp_port = store_get((pct+1) * sizeof(int), FALSE); + default_smtp_port = store_get((pct+1) * sizeof(int), GET_UNTAINTED); list = daemon_smtp_port; sep = 0; for (pct = 0; @@ -1623,7 +1654,7 @@ if (f.daemon_listen && !f.inetd_wait_mode) ipa->port = default_smtp_port[0]; for (int i = 1; default_smtp_port[i] > 0; i++) { - ip_address_item *new = store_get(sizeof(ip_address_item), FALSE); + ip_address_item * new = store_get(sizeof(ip_address_item), GET_UNTAINTED); memcpy(new->address, ipa->address, Ustrlen(ipa->address) + 1); new->port = default_smtp_port[i]; @@ -1683,7 +1714,7 @@ if (f.daemon_listen && !f.inetd_wait_mode) for (ipa = addresses; ipa; ipa = ipa->next) listen_socket_count++; fd_polls = store_get(sizeof(struct pollfd) * (listen_socket_count + 2), - FALSE); + GET_UNTAINTED); for (struct pollfd * p = fd_polls; p < fd_polls + listen_socket_count + 2; p++) { p->fd = -1; p->events = POLLIN; } @@ -1709,7 +1740,7 @@ if (f.daemon_listen) if (smtp_accept_max > 0) { - smtp_slots = store_get(smtp_accept_max * sizeof(smtp_slot), FALSE); + smtp_slots = store_get(smtp_accept_max * sizeof(smtp_slot), GET_UNTAINTED); for (int i = 0; i < smtp_accept_max; i++) smtp_slots[i] = empty_smtp_slot; } } @@ -1746,15 +1777,19 @@ if (f.background_daemon) daemon as the result of a SIGHUP. In this case, there is no need to do anything, because the controlling terminal has long gone. Otherwise, fork, in case current process is a process group leader (see 'man setsid' for an - explanation) before calling setsid(). */ + explanation) before calling setsid(). + All other forks want daemon_listen cleared. Rather than blow a register, jsut + restore it here. */ if (getppid() != 1) { + BOOL daemon_listen = f.daemon_listen; pid_t pid = exim_fork(US"daemon"); if (pid < 0) log_write(0, LOG_MAIN|LOG_PANIC_DIE, "fork() failed when starting daemon: %s", strerror(errno)); if (pid > 0) exit(EXIT_SUCCESS); /* in parent process, just exit */ (void)setsid(); /* release controlling terminal */ + f.daemon_listen = daemon_listen; } } @@ -1991,7 +2026,7 @@ of them (and also if we are doing queue runs). */ if (queue_interval > 0 && local_queue_run_max > 0) { - queue_pid_slots = store_get(local_queue_run_max * sizeof(pid_t), FALSE); + queue_pid_slots = store_get(local_queue_run_max * sizeof(pid_t), GET_UNTAINTED); for (int i = 0; i < local_queue_run_max; i++) queue_pid_slots[i] = 0; } @@ -2092,7 +2127,7 @@ else if (f.daemon_listen) if (*--p == '}') *p = '\0'; /* drop EOL */ while (isdigit(*--p)) ; /* char before port */ - i2->log = *p == ':' /* no list yet? */ + i2->log = *p == ':' /* no list yet? { */ ? string_sprintf("%.*s{%s,%d}", (int)(p - i2->log + 1), i2->log, p+1, ipa->port) : string_sprintf("%s,%d}", i2->log, ipa->port);