From 9a57ef8dbf7d91f745c95b3a06d318994a7b61c8 Mon Sep 17 00:00:00 2001 From: Thomas Kupper Date: Wed, 4 Feb 2026 21:53:52 +0100 Subject: [PATCH] privops: add method PRV_AdjustFreq() In preparation of adding OpenBSD support: OpenBSD doesn't support timex but adjusting frequency using the adjfreq(2) system call. Add a privops method PRV_AdjustFreq() to allow unprivileged processes to set the time. --- privops.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ privops.h | 6 +++++ 2 files changed, 77 insertions(+) diff --git a/privops.c b/privops.c index 16114ce..a42e983 100644 --- a/privops.c +++ b/privops.c @@ -43,6 +43,7 @@ #define OP_BINDSOCKET 1027 #define OP_NAME2IPADDRESS 1028 #define OP_RELOADDNS 1029 +#define OP_ADJUSTFREQ 1030 #define OP_QUIT 1099 union sockaddr_in46 { @@ -79,6 +80,13 @@ typedef struct { char name[256]; } ReqName2IPAddress; +#ifdef PRIVOPS_ADJUSTFREQ +typedef struct { + int64_t freq; + int is_read_adj; +} ReqAdjustFreq; +#endif + typedef struct { int op; union { @@ -90,6 +98,9 @@ typedef struct { ReqBindSocket bind_socket; #ifdef PRIVOPS_NAME2IPADDRESS ReqName2IPAddress name_to_ipaddress; +#endif +#ifdef PRIVOPS_ADJUSTFREQ + ReqAdjustFreq adjust_freq; #endif } data; } PrvRequest; @@ -110,6 +121,10 @@ typedef struct { IPAddr addresses[DNS_MAX_ADDRESSES]; } ResName2IPAddress; +typedef struct { + int64_t oldfreq; +} ResAdjustFreq; + typedef struct { char msg[256]; } ResFatalMsg; @@ -126,6 +141,9 @@ typedef struct { #endif #ifdef PRIVOPS_NAME2IPADDRESS ResName2IPAddress name_to_ipaddress; +#endif +#ifdef PRIVOPS_ADJUSTFREQ + ResAdjustFreq adjust_freq; #endif } data; } PrvResponse; @@ -302,6 +320,22 @@ 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->is_read_adj ? NULL : &req->freq, + &res->data.adjust_freq.oldfreq); + if (res->rc) + res->res_errno = errno; +} +#endif + /* ======================================================================= */ /* HELPER - main loop - action requests from the daemon */ @@ -350,6 +384,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; @@ -625,6 +664,38 @@ 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()) + /* helper is not running */ + return adjfreq(freq, oldfreq); + + memset(&req, 0, sizeof (req)); + req.op = OP_ADJUSTFREQ; + + if (freq == NULL) + req.data.adjust_freq.is_read_adj = 1; + else + 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(int level) { diff --git a/privops.h b/privops.h index 53513c7..fe23613 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(int scfilter_level); void PRV_StartHelper(void);