* 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

Reply via email to