* Henning Brauer <[EMAIL PROTECTED]> [2008-09-10 10:39]: > ntpd -s will time out eventually, but the 'eventually' might be > painfully far away. it's the dns routines that block and cause these > problems. i know how to fix this but haven't found the time to do so > yet. maybe i get a chance on the flight later today. maybe.
didn't find too much time on the flight, but finished this morning. basically, move dns to its own process. the parent process is just not allowed to block no matter what. the dns process can drop privs but not chroot. Index: Makefile =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/Makefile,v retrieving revision 1.8 diff -u -p -r1.8 Makefile --- Makefile 26 May 2006 00:33:16 -0000 1.8 +++ Makefile 11 Sep 2008 10:18:27 -0000 @@ -4,7 +4,7 @@ PROG= ntpd SRCS= ntpd.c buffer.c log.c imsg.c ntp.c ntp_msg.c parse.y config.c \ - server.c client.c sensors.c util.c + server.c client.c sensors.c util.c ntp_dns.c CFLAGS+= -Wall -I${.CURDIR} CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes CFLAGS+= -Wmissing-declarations Index: ntp.c =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntp.c,v retrieving revision 1.106 diff -u -p -r1.106 ntp.c --- ntp.c 10 Jun 2008 03:46:09 -0000 1.106 +++ ntp.c 11 Sep 2008 10:18:28 -0000 @@ -35,11 +35,13 @@ #define PFD_PIPE_MAIN 0 #define PFD_HOTPLUG 1 -#define PFD_MAX 2 +#define PFD_PIPE_DNS 2 +#define PFD_MAX 3 volatile sig_atomic_t ntp_quit = 0; volatile sig_atomic_t ntp_report = 0; struct imsgbuf *ibuf_main; +struct imsgbuf *ibuf_dns; struct ntpd_conf *conf; u_int peer_cnt; u_int sensors_cnt; @@ -47,6 +49,7 @@ time_t lastreport; void ntp_sighdlr(int); int ntp_dispatch_imsg(void); +int ntp_dispatch_imsg_dns(void); void peer_add(struct ntp_peer *); void peer_remove(struct ntp_peer *); void report_peers(int); @@ -69,10 +72,10 @@ pid_t ntp_main(int pipe_prnt[2], struct ntpd_conf *nconf, struct passwd *pw) { int a, b, nfds, i, j, idx_peers, timeout; - int hotplugfd, nullfd; + int hotplugfd, nullfd, pipe_dns[2]; u_int pfd_elms = 0, idx2peer_elms = 0; u_int listener_cnt, new_cnt, sent_cnt, trial_cnt; - pid_t pid; + pid_t pid, dns_pid; struct pollfd *pfd = NULL; struct servent *se; struct listen_addr *la; @@ -107,6 +110,11 @@ ntp_main(int pipe_prnt[2], struct ntpd_c fatal(NULL); hotplugfd = sensor_hotplugfd(); + if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_dns) == -1) + fatal("socketpair"); + dns_pid = ntp_dns(pipe_dns, nconf, pw); + close(pipe_dns[1]); + if (stat(pw->pw_dir, &stb) == -1) fatal("stat"); if (stb.st_uid != 0 || (stb.st_mode & (S_IWGRP|S_IWOTH)) != 0) @@ -146,6 +154,9 @@ ntp_main(int pipe_prnt[2], struct ntpd_c if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf_main, pipe_prnt[1]); + if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) + fatal(NULL); + imsg_init(ibuf_dns, pipe_dns[0]); TAILQ_FOREACH(p, &conf->ntp_peers, entry) client_peer_init(p); @@ -212,6 +223,8 @@ ntp_main(int pipe_prnt[2], struct ntpd_c pfd[PFD_PIPE_MAIN].events = POLLIN; pfd[PFD_HOTPLUG].fd = hotplugfd; pfd[PFD_HOTPLUG].events = POLLIN; + pfd[PFD_PIPE_DNS].fd = ibuf_dns->fd; + pfd[PFD_PIPE_DNS].events = POLLIN; i = PFD_MAX; TAILQ_FOREACH(la, &conf->listen_addrs, entry) { @@ -289,6 +302,8 @@ ntp_main(int pipe_prnt[2], struct ntpd_c if (ibuf_main->w.queued > 0) pfd[PFD_PIPE_MAIN].events |= POLLOUT; + if (ibuf_dns->w.queued > 0) + pfd[PFD_PIPE_DNS].events |= POLLOUT; timeout = nextaction - getmonotime(); if (timeout < 0) @@ -312,6 +327,18 @@ ntp_main(int pipe_prnt[2], struct ntpd_c ntp_quit = 1; } + if (nfds > 0 && (pfd[PFD_PIPE_DNS].revents & POLLOUT)) + if (msgbuf_write(&ibuf_dns->w) < 0) { + log_warn("pipe write error (to dns engine)"); + ntp_quit = 1; + } + + if (nfds > 0 && pfd[PFD_PIPE_DNS].revents & (POLLIN|POLLERR)) { + nfds--; + if (ntp_dispatch_imsg_dns() == -1) + ntp_quit = 1; + } + if (nfds > 0 && pfd[PFD_HOTPLUG].revents & (POLLIN|POLLERR)) { nfds--; sensor_hotplugevent(hotplugfd); @@ -345,6 +372,9 @@ ntp_main(int pipe_prnt[2], struct ntpd_c msgbuf_write(&ibuf_main->w); msgbuf_clear(&ibuf_main->w); free(ibuf_main); + msgbuf_write(&ibuf_dns->w); + msgbuf_clear(&ibuf_dns->w); + free(ibuf_dns); log_info("ntp engine exiting"); _exit(0); @@ -355,10 +385,6 @@ ntp_dispatch_imsg(void) { struct imsg imsg; int n; - struct ntp_peer *peer, *npeer; - u_int16_t dlen; - u_char *p; - struct ntp_addr *h; if ((n = imsg_read(ibuf_main)) == -1) return (-1); @@ -386,6 +412,40 @@ ntp_dispatch_imsg(void) conf->status.synced = 0; } break; + default: + break; + } + imsg_free(&imsg); + } + return (0); +} + +int +ntp_dispatch_imsg_dns(void) +{ + struct imsg imsg; + struct ntp_peer *peer, *npeer; + u_int16_t dlen; + u_char *p; + struct ntp_addr *h; + int n; + + if ((n = imsg_read(ibuf_dns)) == -1) + return (-1); + + if (n == 0) { /* connection closed */ + log_warnx("ntp_dispatch_imsg_dns in ntp engine: pipe closed"); + return (-1); + } + + for (;;) { + if ((n = imsg_get(ibuf_dns, &imsg)) == -1) + return (-1); + + if (n == 0) + break; + + switch (imsg.hdr.type) { case IMSG_HOST_DNS: TAILQ_FOREACH(peer, &conf->ntp_peers, entry) if (peer->id == imsg.hdr.peerid) @@ -633,7 +693,7 @@ priv_host_dns(char *name, u_int32_t peer u_int16_t dlen; dlen = strlen(name) + 1; - imsg_compose(ibuf_main, IMSG_HOST_DNS, peerid, 0, name, dlen); + imsg_compose(ibuf_dns, IMSG_HOST_DNS, peerid, 0, name, dlen); } void @@ -727,4 +787,3 @@ report_peers(int always) } } } - Index: ntp_dns.c =================================================================== RCS file: ntp_dns.c diff -N ntp_dns.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ntp_dns.c 11 Sep 2008 10:18:28 -0000 @@ -0,0 +1,170 @@ +/* $OpenBSD: ntp.c,v 1.103 2008/01/28 11:45:59 mpf Exp $ */ + +/* + * Copyright (c) 2003-2008 Henning Brauer <[EMAIL PROTECTED]> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/time.h> +#include <errno.h> +#include <poll.h> +#include <signal.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "ntpd.h" + +volatile sig_atomic_t quit_dns = 0; +struct imsgbuf *ibuf_dns; + +void sighdlr_dns(int); +int dns_dispatch_imsg(void); + +void +sighdlr_dns(int sig) +{ + switch (sig) { + case SIGTERM: + case SIGINT: + quit_dns = 1; + break; + } +} + +pid_t +ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) +{ + pid_t pid; + struct pollfd pfd[1]; + int nfds; + + switch (pid = fork()) { + case -1: + fatal("cannot fork"); + break; + case 0: + break; + default: + return (pid); + } + + /* in this case the parent didn't init logging and didn't daemonize */ + if (nconf->settime && !nconf->debug) { + log_init(nconf->debug); + if (setsid() == -1) + fatal("setsid"); + } + + setproctitle("dns engine"); + close(pipe_ntp[0]); + + if (setgroups(1, &pw->pw_gid) || + setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || + setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) + fatal("can't drop privileges"); + endservent(); + + signal(SIGTERM, sighdlr_dns); + signal(SIGINT, sighdlr_dns); + signal(SIGHUP, sighdlr_dns); + + if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) + fatal(NULL); + imsg_init(ibuf_dns, pipe_ntp[1]); + + while (quit_dns == 0) { + pfd[0].fd = ibuf_dns->fd; + pfd[0].events = POLLIN; + if (ibuf_dns->w.queued) + pfd[0].events |= POLLOUT; + + if ((nfds = poll(pfd, 1, INFTIM)) == -1) + if (errno != EINTR) { + log_warn("poll error"); + quit_dns = 1; + } + + if (nfds > 0 && (pfd[0].revents & POLLOUT)) + if (msgbuf_write(&ibuf_dns->w) < 0) { + log_warn("pipe write error (to ntp engine)"); + quit_dns = 1; + } + + if (nfds > 0 && pfd[0].revents & POLLIN) { + nfds--; + if (dns_dispatch_imsg() == -1) + quit_dns = 1; + } + } + + msgbuf_clear(&ibuf_dns->w); + free(ibuf_dns); + _exit(0); +} + +int +dns_dispatch_imsg(void) +{ + struct imsg imsg; + int n, cnt; + char *name; + struct ntp_addr *h, *hn; + struct buf *buf; + + if ((n = imsg_read(ibuf_dns)) == -1) + return (-1); + + if (n == 0) { /* connection closed */ + log_warnx("dispatch_imsg in main: pipe closed"); + return (-1); + } + + for (;;) { + if ((n = imsg_get(ibuf_dns, &imsg)) == -1) + return (-1); + + if (n == 0) + break; + + switch (imsg.hdr.type) { + case IMSG_HOST_DNS: + name = imsg.data; + if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE) + fatalx("invalid IMSG_HOST_DNS received"); + imsg.hdr.len -= 1 + IMSG_HEADER_SIZE; + if (name[imsg.hdr.len] != '\0' || + strlen(name) != imsg.hdr.len) + fatalx("invalid IMSG_HOST_DNS received"); + if ((cnt = host_dns(name, &hn)) == -1) + break; + buf = imsg_create(ibuf_dns, IMSG_HOST_DNS, + imsg.hdr.peerid, 0, + cnt * sizeof(struct sockaddr_storage)); + if (buf == NULL) + break; + if (cnt > 0) + for (h = hn; h != NULL; h = h->next) + imsg_add(buf, &h->ss, sizeof(h->ss)); + + imsg_close(ibuf_dns, buf); + break; + default: + break; + } + imsg_free(&imsg); + } + return (0); +} Index: ntpd.h =================================================================== RCS file: /cvs/src/usr.sbin/ntpd/ntpd.h,v retrieving revision 1.95 diff -u -p -r1.95 ntpd.h --- ntpd.h 10 Jun 2008 03:46:09 -0000 1.95 +++ ntpd.h 11 Sep 2008 10:18:28 -0000 @@ -316,3 +316,6 @@ int sensor_scan(void); void sensor_query(struct ntp_sensor *); int sensor_hotplugfd(void); void sensor_hotplugevent(int); + +/* ntp_dns.c */ +pid_t ntp_dns(int[2], struct ntpd_conf *, struct passwd *); -- Henning Brauer, [EMAIL PROTECTED], [EMAIL PROTECTED] BS Web Services, http://bsws.de Full-Service ISP - Secure Hosting, Mail and DNS Services Dedicated Servers, Rootservers, Application Hosting - Hamburg & Amsterdam