From a4d91af57b90f496294ec109a8abcfdaceb54478 Mon Sep 17 00:00:00 2001 From: deraadt <> Date: Fri, 23 Oct 2015 16:39:13 +0000 Subject: [PATCH] Rather than re-opening the driftfile to write, keep it open; rewinding and coping with error conditions... that lets us avoid a pledge "wpath". Putting it all together, this lets the master ntpd pledge "stdio rpath inet settime proc id". It works like this: "rpath" to load the certificates, "proc" to create constraint processes, "id" to chroot and lock the constraint processes into a jail, then "inet" to open a https session. "settime" is used by the master to manage the system time when the ntp-speaking engine instructs the master. with help from naddy --- src/usr.sbin/ntpd/ntpd.c | 50 ++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/usr.sbin/ntpd/ntpd.c b/src/usr.sbin/ntpd/ntpd.c index cc9b3077..5c4d4103 100644 --- a/src/usr.sbin/ntpd/ntpd.c +++ b/src/usr.sbin/ntpd/ntpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ntpd.c,v 1.97 2015/10/12 06:50:08 reyk Exp $ */ +/* $OpenBSD: ntpd.c,v 1.98 2015/10/23 16:39:13 deraadt Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "ntpd.h" @@ -215,6 +216,13 @@ main(int argc, char *argv[]) constraint_cnt = 0; + /* + * Constraint processes are forked with certificates in memory, + * then privdrop into chroot before speaking to the outside world. + */ + if (pledge("stdio rpath inet settime proc id", NULL) == -1) + err(1, "pledge"); + while (quit == 0) { new_cnt = PFD_MAX + constraint_cnt; if (new_cnt > pfd_elms) { @@ -491,61 +499,59 @@ ntpd_settime(double d) log_info("set local clock to %s (offset %fs)", buf, d); } +static FILE *freqfp; + void readfreq(void) { - FILE *fp; int64_t current; + int fd; double d; - fp = fopen(DRIFTFILE, "r"); - if (fp == NULL) { - /* if the drift file has been deleted by the user, reset */ + fd = open(DRIFTFILE, O_RDWR); + if (fd == -1) { + log_warnx("creating new %s", DRIFTFILE); current = 0; if (adjfreq(¤t, NULL) == -1) log_warn("adjfreq reset failed"); + freqfp = fopen(DRIFTFILE, "w"); return; } + + freqfp = fdopen(fd, "r+"); /* if we're adjusting frequency already, don't override */ if (adjfreq(NULL, ¤t) == -1) log_warn("adjfreq failed"); - else if (current == 0) { - if (fscanf(fp, "%lf", &d) == 1) { + else if (current == 0 && freqfp) { + if (fscanf(freqfp, "%lf", &d) == 1) { d /= 1e6; /* scale from ppm */ ntpd_adjfreq(d, 0); } else - log_warnx("can't read %s", DRIFTFILE); + log_warnx("%s is empty", DRIFTFILE); } - fclose(fp); } int writefreq(double d) { int r; - FILE *fp; static int warnonce = 1; - fp = fopen(DRIFTFILE, "w"); - if (fp == NULL) { - if (warnonce) { - log_warn("can't open %s", DRIFTFILE); - warnonce = 0; - } + if (freqfp == NULL) return 0; - } - - fprintf(fp, "%.3f\n", d * 1e6); /* scale to ppm */ - r = ferror(fp); - if (fclose(fp) != 0 || r != 0) { + rewind(freqfp); + fprintf(freqfp, "%.3f\n", d * 1e6); /* scale to ppm */ + r = ferror(freqfp); + if (r != 0) { if (warnonce) { log_warnx("can't write %s", DRIFTFILE); warnonce = 0; } - unlink(DRIFTFILE); return 0; } + ftruncate(fileno(freqfp), ftello(freqfp)); + fsync(fileno(freqfp)); return 1; }