diff options
-rw-r--r-- | usr.sbin/ntpd/control.c | 4 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntp.c | 38 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntp_dns.c | 23 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntpd.c | 40 | ||||
-rw-r--r-- | usr.sbin/ntpd/ntpd.h | 13 | ||||
-rw-r--r-- | usr.sbin/ntpd/util.c | 81 |
6 files changed, 142 insertions, 57 deletions
diff --git a/usr.sbin/ntpd/control.c b/usr.sbin/ntpd/control.c index 1fc7375c246..a9a3941a7ca 100644 --- a/usr.sbin/ntpd/control.c +++ b/usr.sbin/ntpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.10 2016/03/27 11:16:12 krw Exp $ */ +/* $OpenBSD: control.c,v 1.11 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -43,7 +43,7 @@ control_init(char *path) int fd; mode_t old_umask; - if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { + if ((fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1) { log_warn("control_init: socket"); return (-1); } diff --git a/usr.sbin/ntpd/ntp.c b/usr.sbin/ntpd/ntp.c index 76b04f25efe..9c03747e33f 100644 --- a/usr.sbin/ntpd/ntp.c +++ b/usr.sbin/ntpd/ntp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp.c,v 1.142 2016/09/03 11:52:06 reyk Exp $ */ +/* $OpenBSD: ntp.c,v 1.143 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -66,17 +66,16 @@ ntp_sighdlr(int sig) } } -pid_t -ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, - struct passwd *pw) +void +ntp_main(struct ntpd_conf *nconf, struct passwd *pw, int argc, char **argv) { int a, b, nfds, i, j, idx_peers, timeout; int nullfd, pipe_dns[2], idx_clients; int ctls; + int fd_ctl; u_int pfd_elms = 0, idx2peer_elms = 0; u_int listener_cnt, new_cnt, sent_cnt, trial_cnt; u_int ctl_cnt; - pid_t pid; struct pollfd *pfd = NULL; struct servent *se; struct listen_addr *la; @@ -90,15 +89,11 @@ ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, time_t nextaction, last_sensor_scan = 0, now; void *newp; - switch (pid = fork()) { - case -1: - fatal("cannot fork"); - break; - case 0: - break; - default: - return (pid); - } + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, + pipe_dns) == -1) + fatal("socketpair"); + + start_child(NTPDNS_PROC_NAME, pipe_dns[1], argc, argv); /* in this case the parent didn't init logging and didn't daemonize */ if (nconf->settime && !nconf->debug) { @@ -111,15 +106,14 @@ ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, if ((se = getservbyname("ntp", "udp")) == NULL) fatal("getservbyname"); + /* Start control socket. */ + if ((fd_ctl = control_init(CTLSOCKET)) == -1) + fatalx("control socket init failed"); + if (control_listen(fd_ctl) == -1) + fatalx("control socket listen failed"); if ((nullfd = open("/dev/null", O_RDWR, 0)) == -1) fatal(NULL); - close(pipe_prnt[0]); - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_dns) == -1) - fatal("socketpair"); - ntp_dns(pipe_dns, nconf, pw); - close(pipe_dns[1]); - if (stat(pw->pw_dir, &stb) == -1) { fatal("privsep dir %s could not be opened", pw->pw_dir); } @@ -163,7 +157,7 @@ ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, if ((ibuf_main = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); - imsg_init(ibuf_main, pipe_prnt[1]); + imsg_init(ibuf_main, PARENT_SOCK_FILENO); if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); imsg_init(ibuf_dns, pipe_dns[0]); @@ -422,7 +416,7 @@ ntp_main(int pipe_prnt[2], int fd_ctl, struct ntpd_conf *nconf, free(ibuf_dns); log_info("ntp engine exiting"); - _exit(0); + exit(0); } int diff --git a/usr.sbin/ntpd/ntp_dns.c b/usr.sbin/ntpd/ntp_dns.c index 044cb4fe7a4..a8dcf98c60b 100644 --- a/usr.sbin/ntpd/ntp_dns.c +++ b/usr.sbin/ntpd/ntp_dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntp_dns.c,v 1.17 2016/09/03 11:52:06 reyk Exp $ */ +/* $OpenBSD: ntp_dns.c,v 1.18 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org> @@ -49,23 +49,12 @@ sighdlr_dns(int sig) } } -pid_t -ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) +void +ntp_dns(struct ntpd_conf *nconf, struct passwd *pw) { - pid_t pid; struct pollfd pfd[1]; int nfds, nullfd; - switch (pid = fork()) { - case -1: - fatal("cannot fork"); - break; - case 0: - break; - default: - return (pid); - } - if (setpriority(PRIO_PROCESS, 0, 0) == -1) log_warn("could not set priority"); @@ -89,8 +78,6 @@ ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) 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)) @@ -102,7 +89,7 @@ ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) if ((ibuf_dns = malloc(sizeof(struct imsgbuf))) == NULL) fatal(NULL); - imsg_init(ibuf_dns, pipe_ntp[1]); + imsg_init(ibuf_dns, PARENT_SOCK_FILENO); if (pledge("stdio dns", NULL) == -1) err(1, "pledge"); @@ -135,7 +122,7 @@ ntp_dns(int pipe_ntp[2], struct ntpd_conf *nconf, struct passwd *pw) msgbuf_clear(&ibuf_dns->w); free(ibuf_dns); - _exit(0); + exit(0); } int diff --git a/usr.sbin/ntpd/ntpd.c b/usr.sbin/ntpd/ntpd.c index 7e15213271b..2df47e84852 100644 --- a/usr.sbin/ntpd/ntpd.c +++ b/usr.sbin/ntpd/ntpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.c,v 1.108 2016/09/03 11:52:06 reyk Exp $ */ +/* $OpenBSD: ntpd.c,v 1.109 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -112,7 +112,7 @@ main(int argc, char *argv[]) struct pollfd *pfd = NULL; pid_t chld_pid = 0, pid; const char *conffile; - int fd_ctl, ch, nfds, i, j; + int ch, nfds, i, j; int pipe_chld[2]; extern char *__progname; u_int pfd_elms = 0, new_cnt; @@ -122,6 +122,9 @@ main(int argc, char *argv[]) uid_t pw_uid; gid_t pw_gid; void *newp; + int argc0 = argc; + char **argv0 = argv; + char *pname = NULL; if (strcmp(__progname, "ntpctl") == 0) { ctl_main(argc, argv); @@ -132,7 +135,7 @@ main(int argc, char *argv[]) memset(&lconf, 0, sizeof(lconf)); - while ((ch = getopt(argc, argv, "df:nsSv")) != -1) { + while ((ch = getopt(argc, argv, "df:nP:sSv")) != -1) { switch (ch) { case 'd': lconf.debug = 2; @@ -144,6 +147,9 @@ main(int argc, char *argv[]) lconf.debug = 2; lconf.noaction = 1; break; + case 'P': + pname = optarg; + break; case 's': lconf.settime = 1; break; @@ -181,6 +187,22 @@ main(int argc, char *argv[]) if ((pw = getpwnam(NTPD_USER)) == NULL) errx(1, "unknown user %s", NTPD_USER); + if (pname != NULL) { + /* Remove our proc arguments, so child doesn't need to. */ + if (sanitize_argv(&argc0, &argv0) == -1) + fatalx("sanitize_argv"); + + if (strcmp(NTP_PROC_NAME, pname) == 0) + ntp_main(&lconf, pw, argc0, argv0); + else if (strcmp(NTPDNS_PROC_NAME, pname) == 0) + ntp_dns(&lconf, pw); + else + fatalx("%s: invalid process name '%s'", __func__, + pname); + + fatalx("%s: process '%s' failed", __func__, pname); + } + pw_dir = strdup(pw->pw_dir); pw_uid = pw->pw_uid; pw_gid = pw->pw_gid; @@ -198,17 +220,14 @@ main(int argc, char *argv[]) } else timeout = SETTIME_TIMEOUT * 1000; - if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1) + if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, PF_UNSPEC, + pipe_chld) == -1) fatal("socketpair"); - if ((fd_ctl = control_init(CTLSOCKET)) == -1) - fatalx("control socket init failed"); - if (control_listen(fd_ctl) == -1) - fatalx("control socket listen failed"); - signal(SIGCHLD, sighdlr); + /* fork child process */ - chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw); + chld_pid = start_child(NTP_PROC_NAME, pipe_chld[1], argc0, argv0); log_procinit("[priv]"); readfreq(); @@ -217,7 +236,6 @@ main(int argc, char *argv[]) signal(SIGINT, sighdlr); signal(SIGHUP, sighdlr); - close(pipe_chld[1]); constraint_purge(); if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL) diff --git a/usr.sbin/ntpd/ntpd.h b/usr.sbin/ntpd/ntpd.h index ae774d8bb37..8a67470219b 100644 --- a/usr.sbin/ntpd/ntpd.h +++ b/usr.sbin/ntpd/ntpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.h,v 1.131 2016/09/03 11:52:06 reyk Exp $ */ +/* $OpenBSD: ntpd.h,v 1.132 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -82,6 +82,11 @@ #define CONSTRAINT_PASSFD (STDERR_FILENO + 1) #define CONSTRAINT_CA "/etc/ssl/cert.pem" +#define PARENT_SOCK_FILENO 3 + +#define NTP_PROC_NAME "ntp_main" +#define NTPDNS_PROC_NAME "ntp_dns" + enum client_state { STATE_NONE, STATE_DNS_INPROGRESS, @@ -302,7 +307,7 @@ enum ctl_actions { /* prototypes */ /* ntp.c */ -pid_t ntp_main(int[2], int, struct ntpd_conf *, struct passwd *); +void ntp_main(struct ntpd_conf *, struct passwd *, int, char **); int priv_adjtime(void); void priv_settime(double); void priv_dns(int, char *, u_int32_t); @@ -372,6 +377,8 @@ double sfp_to_d(struct s_fixedpt); struct s_fixedpt d_to_sfp(double); char *print_rtable(int); const char *log_sockaddr(struct sockaddr *); +pid_t start_child(char *, int, int, char **); +int sanitize_argv(int *, char ***); /* sensors.c */ void sensor_init(void); @@ -379,7 +386,7 @@ int sensor_scan(void); void sensor_query(struct ntp_sensor *); /* ntp_dns.c */ -pid_t ntp_dns(int[2], struct ntpd_conf *, struct passwd *); +void ntp_dns(struct ntpd_conf *, struct passwd *); /* control.c */ int control_init(char *); diff --git a/usr.sbin/ntpd/util.c b/usr.sbin/ntpd/util.c index e15b1f863b4..146834b5eca 100644 --- a/usr.sbin/ntpd/util.c +++ b/usr.sbin/ntpd/util.c @@ -1,4 +1,4 @@ -/* $OpenBSD: util.c,v 1.21 2016/09/14 08:24:08 reyk Exp $ */ +/* $OpenBSD: util.c,v 1.22 2016/09/14 13:20:16 rzalamena Exp $ */ /* * Copyright (c) 2004 Alexander Guy <alexander.guy@andern.org> @@ -18,7 +18,9 @@ #include <limits.h> #include <stdio.h> +#include <stdlib.h> #include <time.h> +#include <unistd.h> #include "ntpd.h" @@ -151,3 +153,80 @@ log_sockaddr(struct sockaddr *sa) else return (buf); } + +pid_t +start_child(char *pname, int cfd, int argc, char **argv) +{ + char **nargv; + int nargc, i; + pid_t pid; + + /* Prepare the child process new argv. */ + nargv = calloc(argc + 3, sizeof(char *)); + if (nargv == NULL) + fatal("%s: calloc", __func__); + + /* Copy the program name first. */ + nargc = 0; + nargv[nargc++] = argv[0]; + + /* Set the process name and copy the original args. */ + nargv[nargc++] = "-P"; + nargv[nargc++] = pname; + for (i = 1; i < argc; i++) + nargv[nargc++] = argv[i]; + + nargv[nargc] = 0; + + switch (pid = fork()) { + case -1: + fatal("%s: fork", __func__); + break; + case 0: + /* Prepare the parent socket and execute. */ + dup2(cfd, PARENT_SOCK_FILENO); + + execvp(argv[0], nargv); + fatal("%s: execvp", __func__); + break; + + default: + /* Close child's socket end. */ + close(cfd); + break; + } + + free(nargv); + return (pid); +} + +int +sanitize_argv(int *argc, char ***argv) +{ + char **nargv; + int nargc; + int i; + + /* + * We need at least three arguments: + * Example: '/usr/sbin/ntpd' '-P' 'foobar'. + */ + if (*argc < 3) + return (-1); + + *argc -= 2; + + /* Allocate new arguments vector and copy pointers. */ + nargv = calloc((*argc) + 1, sizeof(char *)); + if (nargv == NULL) + return (-1); + + nargc = 0; + nargv[nargc++] = (*argv)[0]; + for (i = 1; i < *argc; i++) + nargv[nargc++] = (*argv)[i + 2]; + + nargv[nargc] = NULL; + *argv = nargv; + return (0); +} |