chrony/sys_netbsd.c
Miroslav Lichvar 46f0ad6b53 sys_netbsd: use privileged helper for socket binding
When dropping root privileges, start the helper to allow binding
of server sockets later.
2015-12-08 18:02:05 +01:00

147 lines
4 KiB
C

/*
chronyd/chronyc - Programs for keeping computer clocks accurate.
**********************************************************************
* Copyright (C) Richard P. Curnow 1997-2001
* Copyright (C) J. Hannken-Illjes 2001
* Copyright (C) Miroslav Lichvar 2015
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
**********************************************************************
=======================================================================
Driver file for the NetBSD operating system.
*/
#include "config.h"
#include "sysincl.h"
#include "sys_netbsd.h"
#include "sys_timex.h"
#include "logging.h"
#include "privops.h"
#include "util.h"
/* Maximum frequency offset accepted by the kernel (in ppm) */
#define MAX_FREQ 500.0
/* Minimum assumed rate at which the kernel updates the clock frequency */
#define MIN_TICK_RATE 100
/* Interval between kernel updates of the adjtime() offset */
#define ADJTIME_UPDATE_INTERVAL 1.0
/* Maximum adjtime() slew rate (in ppm) */
#define MAX_ADJTIME_SLEWRATE 5000.0
/* Minimum offset adjtime() slews faster than MAX_FREQ */
#define MIN_FASTSLEW_OFFSET 1.0
/* ================================================== */
/* Positive offset means system clock is fast of true time, therefore
slew backwards */
static void
accrue_offset(double offset, double corr_rate)
{
struct timeval newadj, oldadj;
UTI_DoubleToTimeval(-offset, &newadj);
if (adjtime(&newadj, &oldadj) < 0)
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
/* Add the old remaining adjustment if not zero */
UTI_TimevalToDouble(&oldadj, &offset);
if (offset != 0.0) {
UTI_AddDoubleToTimeval(&newadj, offset, &newadj);
if (adjtime(&newadj, NULL) < 0)
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
}
}
/* ================================================== */
static void
get_offset_correction(struct timeval *raw,
double *corr, double *err)
{
struct timeval remadj;
double adjustment_remaining;
if (adjtime(NULL, &remadj) < 0)
LOG_FATAL(LOGF_SysNetBSD, "adjtime() failed");
UTI_TimevalToDouble(&remadj, &adjustment_remaining);
*corr = adjustment_remaining;
if (err) {
if (*corr != 0.0)
*err = 1.0e-6 * MAX_ADJTIME_SLEWRATE / ADJTIME_UPDATE_INTERVAL;
else
*err = 0.0;
}
}
/* ================================================== */
void
SYS_NetBSD_Initialise(void)
{
SYS_Timex_InitialiseWithFunctions(MAX_FREQ, 1.0 / MIN_TICK_RATE,
NULL, NULL, NULL,
MIN_FASTSLEW_OFFSET, MAX_ADJTIME_SLEWRATE,
accrue_offset, get_offset_correction);
}
/* ================================================== */
void
SYS_NetBSD_Finalise(void)
{
SYS_Timex_Finalise();
}
/* ================================================== */
#ifdef FEAT_PRIVDROP
void
SYS_NetBSD_DropRoot(uid_t uid, gid_t gid)
{
int fd;
PRV_StartHelper();
if (setgroups(0, NULL))
LOG_FATAL(LOGF_SysNetBSD, "setgroups() failed : %s", strerror(errno));
if (setgid(gid))
LOG_FATAL(LOGF_SysNetBSD, "setgid(%d) failed : %s", gid, strerror(errno));
if (setuid(uid))
LOG_FATAL(LOGF_SysNetBSD, "setuid(%d) failed : %s", uid, strerror(errno));
DEBUG_LOG(LOGF_SysNetBSD, "Root dropped to uid %d gid %d", uid, gid);
/* Check if we have write access to /dev/clockctl */
fd = open("/dev/clockctl", O_WRONLY);
if (fd < 0)
LOG_FATAL(LOGF_SysNetBSD, "Can't write to /dev/clockctl");
close(fd);
}
#endif