[chrony-dev] [PATCH] Add support for OpenBSD

[ Thread Index | Date Index | More chrony.tuxfamily.org/chrony-dev Archives ]


---
 configure     |  12 +++++
 privops.c     |  71 +++++++++++++++++++++++++
 privops.h     |   6 +++
 sys.c         |   9 ++++
 sys_openbsd.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++
 sys_openbsd.h |  39 ++++++++++++++
 sysincl.h     |   4 ++
 7 files changed, 283 insertions(+)
 create mode 100644 sys_openbsd.c
 create mode 100644 sys_openbsd.h

diff --git a/configure b/configure
index 8041d4e..fe40b61 100755
--- a/configure
+++ b/configure
@@ -446,6 +446,18 @@ case $OPERATINGSYSTEM in
         add_def NETBSD
         echo "Configuring for $SYSTEM"
     ;;
+    OpenBSD)
+        try_recvmmsg=0
+        EXTRA_OBJECTS="sys_generic.o sys_openbsd.o sys_posix.o"
+        try_setched=1
+        try_lockmem=1
+        add_def OPENBSD
+        if [ $feat_droproot = "1" ]; then
+          add_def FEAT_PRIVDROP
+          priv_ops="ADJUSTTIME ADJUSTFREQ SETTIME"
+        fi
+        echo "Configuring for $SYSTEM"
+    ;;
     Darwin)
         EXTRA_OBJECTS="sys_macosx.o"
         LIBS="$LIBS -lresolv"
diff --git a/privops.c b/privops.c
index 3fb5cbd..64aa7d7 100644
--- a/privops.c
+++ b/privops.c
@@ -42,6 +42,7 @@
 #define OP_BINDSOCKET     1027
 #define OP_NAME2IPADDRESS 1028
 #define OP_RELOADDNS      1029
+#define OP_ADJUSTFREQ     1030
 #define OP_QUIT           1099
 
 union sockaddr_in46 {
@@ -78,6 +79,12 @@ typedef struct {
   char name[256];
 } ReqName2IPAddress;
 
+#ifdef PRIVOPS_ADJUSTFREQ
+typedef struct {
+  int64_t freq;
+} ReqAdjustFreq;
+#endif
+
 typedef struct {
   int op;
   union {
@@ -89,6 +96,9 @@ typedef struct {
     ReqBindSocket bind_socket;
 #ifdef PRIVOPS_NAME2IPADDRESS
     ReqName2IPAddress name_to_ipaddress;
+#endif
+#ifdef PRIVOPS_ADJUSTFREQ
+    ReqAdjustFreq adjust_freq;
 #endif
   } data;
 } PrvRequest;
@@ -109,6 +119,10 @@ typedef struct {
   IPAddr addresses[DNS_MAX_ADDRESSES];
 } ResName2IPAddress;
 
+typedef struct {
+  int64_t oldfreq;
+} ResAdjustFreq;
+
 typedef struct {
   char msg[256];
 } ResFatalMsg;
@@ -125,6 +139,9 @@ typedef struct {
 #endif
 #ifdef PRIVOPS_NAME2IPADDRESS
     ResName2IPAddress name_to_ipaddress;
+#endif
+#ifdef PRIVOPS_ADJUSTFREQ
+    ResAdjustFreq adjust_freq;
 #endif
   } data;
 } PrvResponse;
@@ -299,6 +316,21 @@ do_reload_dns(PrvResponse *res)
 }
 #endif
 
+
+/* ======================================================================= */
+
+/* HELPER - perform adjustfreq() */
+
+#ifdef PRIVOPS_ADJUSTFREQ
+static void
+do_adjust_freq(const ReqAdjustFreq *req, PrvResponse *res)
+{
+  res->rc = adjfreq(&req->freq, &res->data.adjust_freq.oldfreq);
+  if (res->rc)
+    res->res_errno = errno;
+}
+#endif
+
 /* ======================================================================= */
 
 /* HELPER - main loop - action requests from the daemon */
@@ -347,6 +379,11 @@ helper_main(int fd)
       case OP_RELOADDNS:
         do_reload_dns(&res);
         break;
+#endif
+#ifdef PRIVOPS_ADJUSTFREQ
+      case OP_ADJUSTFREQ:
+        do_adjust_freq(&req.data.adjust_freq, &res);
+        break;
 #endif
       case OP_QUIT:
         quit = 1;
@@ -623,6 +660,34 @@ PRV_ReloadDNS(void)
 
 /* ======================================================================= */
 
+/* DAEMON - request adjfreq() */
+
+#ifdef PRIVOPS_ADJUSTFREQ
+int
+PRV_AdjustFreq(const int64_t *freq, int64_t *oldfreq)
+{
+  PrvRequest req;
+  PrvResponse res;
+
+  if (!have_helper() || freq == NULL)
+    /* helper is not running or read adjustment call */
+    return adjfreq(freq, oldfreq);
+
+  memset(&req, 0, sizeof (req));
+  req.op = OP_ADJUSTFREQ;
+  req.data.adjust_freq.freq = *freq;
+
+  submit_request(&req, &res);
+
+  if (oldfreq)
+    *oldfreq = res.data.adjust_freq.oldfreq;
+
+  return res.rc;
+}
+#endif
+
+/* ======================================================================= */
+
 void
 PRV_Initialise(void)
 {
@@ -667,6 +732,12 @@ PRV_StartHelper(void)
     /* ignore signals, the process will exit on OP_QUIT request */
     UTI_SetQuitSignalsHandler(SIG_IGN, 1);
 
+
+#ifdef OPENBSD
+    if (pledge("stdio unix settime", NULL) == -1)
+      LOG_FATAL("pledge() failed");
+#endif
+
     helper_main(sock_fd2);
 
   } else {
diff --git a/privops.h b/privops.h
index 146580b..fdd0844 100644
--- a/privops.h
+++ b/privops.h
@@ -64,6 +64,12 @@ void PRV_ReloadDNS(void);
 #define PRV_ReloadDNS DNS_Reload
 #endif
 
+#ifdef PRIVOPS_ADJUSTFREQ
+int PRV_AdjustFreq(const int64_t *freq, int64_t *oldfreq);
+#else
+#define PRV_AdjustFreq adjfreq
+#endif
+
 #ifdef PRIVOPS_HELPER
 void PRV_Initialise(void);
 void PRV_StartHelper(void);
diff --git a/sys.c b/sys.c
index 1a1a432..6f597af 100644
--- a/sys.c
+++ b/sys.c
@@ -42,6 +42,9 @@
 #elif defined(NETBSD) || defined(FREEBSD)
 #include "sys_netbsd.h"
 #include "sys_posix.h"
+#elif defined(OPENBSD)
+#include "sys_openbsd.h"
+#include "sys_posix.h"
 #elif defined(MACOSX)
 #include "sys_macosx.h"
 #endif
@@ -66,6 +69,8 @@ SYS_Initialise(int clock_control)
   SYS_Solaris_Initialise();
 #elif defined(NETBSD) || defined(FREEBSD)
   SYS_NetBSD_Initialise();
+#elif defined(OPENBSD)
+  SYS_OpenBSD_Initialise();
 #elif defined(MACOSX)
   SYS_MacOSX_Initialise();
 #else
@@ -88,6 +93,8 @@ SYS_Finalise(void)
   SYS_Solaris_Finalise();
 #elif defined(NETBSD) || defined(FREEBSD)
   SYS_NetBSD_Finalise();
+#elif defined(OPENBSD)
+  SYS_OpenBSD_Finalise();
 #elif defined(MACOSX)
   SYS_MacOSX_Finalise();
 #else
@@ -105,6 +112,8 @@ void SYS_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context)
   SYS_Solaris_DropRoot(uid, gid, context);
 #elif (defined(NETBSD) || defined(FREEBSD)) && defined(FEAT_PRIVDROP)
   SYS_NetBSD_DropRoot(uid, gid, context, !null_driver);
+#elif defined(OPENBSD) && defined(FEAT_PRIVDROP)
+  SYS_OpenBSD_DropRoot(uid, gid, context, !null_driver);
 #elif defined(MACOSX) && defined(FEAT_PRIVDROP)
   SYS_MacOSX_DropRoot(uid, gid, context);
 #else
diff --git a/sys_openbsd.c b/sys_openbsd.c
new file mode 100644
index 0000000..1c8f781
--- /dev/null
+++ b/sys_openbsd.c
@@ -0,0 +1,142 @@
+/*
+  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
+ * Copyright (C) Shaun Ren  2021
+ * 
+ * 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 OpenBSD operating system.
+  */
+
+#include "config.h"
+
+#include "sysincl.h"
+
+#include "sys_generic.h"
+#include "sys_openbsd.h"
+#include "logging.h"
+#include "privops.h"
+#include "util.h"
+
+/* Maximum frequency offset accepted by the kernel (in ppm) */
+#define MAX_FREQ 500000.0
+
+/* ================================================== */
+
+static double
+read_frequency(void)
+{
+  int64_t freq;
+
+  if (PRV_AdjustFreq(NULL, &freq))
+    LOG_FATAL("adjfreq() failed");
+
+  return (double)-freq / (1000LL << 32);
+}
+
+/* ================================================== */
+
+static double
+set_frequency(double freq_ppm)
+{
+  int64_t freq;
+
+  freq = -freq_ppm * (1000LL << 32);
+  if (PRV_AdjustFreq(&freq, NULL))
+    LOG_FATAL("adjfreq() failed");
+
+  return read_frequency();
+}
+
+/* ================================================== */
+
+static struct clockinfo
+get_clockinfo(void)
+{
+  struct clockinfo cinfo;
+  size_t cinfo_len;
+  int mib[2];
+
+  cinfo_len = sizeof(cinfo);
+  mib[0] = CTL_KERN;
+  mib[1] = KERN_CLOCKRATE;
+
+  if (sysctl(mib, 2, &cinfo, &cinfo_len, NULL, 0) == -1)
+    LOG_FATAL("sysctl() failed");
+
+  return cinfo;
+}
+
+/* ================================================== */
+
+static void
+reset_adjtime_offset(void)
+{
+  struct timeval delta;
+  
+  memset(&delta, 0, sizeof(delta));
+
+  if (PRV_AdjustTime(&delta, NULL))
+    LOG_FATAL("adjtime() failed");
+}
+
+
+/* ================================================== */
+
+void
+SYS_OpenBSD_Initialise(void)
+{
+  struct clockinfo cinfo;
+
+  cinfo = get_clockinfo();
+  reset_adjtime_offset();
+
+  SYS_Generic_CompleteFreqDriver(MAX_FREQ, 1.0 / cinfo.hz,
+                                 read_frequency, set_frequency, NULL,
+                                 0.0, 0.0,
+                                 NULL, NULL,
+                                 NULL, NULL);
+}
+
+/* ================================================== */
+
+void
+SYS_OpenBSD_Finalise(void)
+{
+  SYS_Generic_Finalise();
+}
+
+/* ================================================== */
+
+#ifdef FEAT_PRIVDROP
+void
+SYS_OpenBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control)
+{
+  if (context == SYS_MAIN_PROCESS)
+    PRV_StartHelper();
+
+  UTI_DropRoot(uid, gid);
+
+  if (pledge("stdio rpath wpath cpath unix inet dns settime", NULL) == -1)
+    LOG_FATAL("pledge() failed");
+}
+#endif
diff --git a/sys_openbsd.h b/sys_openbsd.h
new file mode 100644
index 0000000..d4cf7ef
--- /dev/null
+++ b/sys_openbsd.h
@@ -0,0 +1,39 @@
+/*
+  chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Richard P. Curnow  1997-2001
+ * Copyright (C) J. Hannken-Illjes  2001
+ * 
+ * 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.
+ * 
+ **********************************************************************
+
+  =======================================================================
+
+  Header file for OpenBSD driver
+  */
+
+#ifndef GOT_SYS_OPENBSD_H
+#define GOT_SYS_OPENBSD_H
+
+#include "sys.h"
+
+void SYS_OpenBSD_Initialise(void);
+
+void SYS_OpenBSD_Finalise(void);
+
+void SYS_OpenBSD_DropRoot(uid_t uid, gid_t gid, SYS_ProcessContext context, int clock_control);
+
+#endif
diff --git a/sysincl.h b/sysincl.h
index e26b236..3494481 100644
--- a/sysincl.h
+++ b/sysincl.h
@@ -62,6 +62,10 @@
 #include <sys/timex.h>
 #endif
 
+#if defined(OPENBSD)
+#include <sys/sysctl.h>
+#endif
+
 #ifdef HAVE_GETRANDOM
 #include <sys/random.h>
 #endif
-- 
2.34.0


-- 
To unsubscribe email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "unsubscribe" in the subject.
For help email chrony-dev-request@xxxxxxxxxxxxxxxxxxxx with "help" in the subject.
Trouble?  Email listmaster@xxxxxxxxxxxxxxxxxxxx.


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/