tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
/dev/clockctl, O_CLOEXEC and forking
While looking whether it's possible to change ntpd to work when
chrooted to a file system mounted with the nodev flag, I noticed
that /dev/clockctl is open with O_CLOEXEC and its file descriptor
is kept in a static variable. I'm not sure it will work after a
fork correctly. ntpd doesn't open /dev/clockctl before forking but
things may change in a future. Any opinions?
PS I attach my proof-of-concept patch that attempts to configure
/dev/clockctl before chrooting ntpd but it doesn't work because
clockctl's file descriptor is closed by the fork.
--
Alex
Index: src/external/bsd/ntp/dist/ntpd/ntpd.c
===================================================================
RCS file: /cvsroot/src/external/bsd/ntp/dist/ntpd/ntpd.c,v
retrieving revision 1.15
diff -p -u -u -r1.15 ntpd.c
--- src/external/bsd/ntp/dist/ntpd/ntpd.c 7 Apr 2018 00:19:53 -0000 1.15
+++ src/external/bsd/ntp/dist/ntpd/ntpd.c 29 Apr 2018 16:06:36 -0000
@@ -214,6 +214,10 @@ extern int syscall (int, ...);
static volatile int signalled = 0;
static volatile int signo = 0;
+#if 1 /* XXX HAVE_CLOCKCTL_CONFIGURE */
+extern int clockctl_configure(void);
+#endif
+
/* In an ideal world, 'finish_safe()' would declared as noreturn... */
static void finish_safe (int);
static RETSIGTYPE finish (int);
@@ -1027,6 +1031,11 @@ getgroup:
msyslog(LOG_ERR, "Cannot chdir() to `%s': %m", chrootdir);
exit (-1);
}
+#if 1 /* XXX HAVE_CLOCKCTL_CONFIGURE */
+ /* open /dev/clockctl while it's still accessible */
+ if (user != NULL)
+ clockctl_configure();
+#endif
if (chroot(chrootdir)) {
msyslog(LOG_ERR, "Cannot chroot() to `%s': %m", chrootdir);
exit (-1);
Index: src/lib/libc/sys/clock_settime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/clock_settime.c,v
retrieving revision 1.12
diff -p -u -u -r1.12 clock_settime.c
--- src/lib/libc/sys/clock_settime.c 15 Oct 2011 23:00:02 -0000 1.12
+++ src/lib/libc/sys/clock_settime.c 29 Apr 2018 16:06:36 -0000
@@ -51,23 +51,23 @@ __RCSID("$NetBSD: clock_settime.c,v 1.12
#include <sys/clockctl.h>
-extern int __clockctl_fd;
-
+int clockctl_configure(void);
+int clockctl_is_configured(void);
int ____clock_settime50(clockid_t, const struct timespec *);
int
clock_settime(clockid_t clock_id, const struct timespec *tp)
{
struct clockctl_clock_settime args;
- int rv;
+ int rv, clockctl = -1;
/*
* always try the syscall first and attempt to switch to
* clockctl if that fails.
*/
- if (__clockctl_fd == -1) {
+ if (!clockctl_is_configured()) {
rv = ____clock_settime50(clock_id, tp);
-
+
/*
* return unless we failed with EPERM
*/
@@ -78,19 +78,18 @@ clock_settime(clockid_t clock_id, const
* If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure.
*/
- __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
- if (__clockctl_fd == -1) {
+ if ((clockctl = clockctl_configure()) == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1;
}
}
- /*
- * If __clockctl_fd >=0, clockctl has already been open
+ /*
+ * If we're here, clockctl has already been open
* and used, so we carry on using it.
*/
args.clock_id = clock_id;
args.tp = tp;
- return ioctl(__clockctl_fd, CLOCKCTL_CLOCK_SETTIME, &args);
+ return ioctl(clockctl, CLOCKCTL_CLOCK_SETTIME, &args);
}
Index: src/lib/libc/sys/adjtime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/adjtime.c,v
retrieving revision 1.12
diff -p -u -u -r1.12 adjtime.c
--- src/lib/libc/sys/adjtime.c 15 Oct 2011 23:00:02 -0000 1.12
+++ src/lib/libc/sys/adjtime.c 29 Apr 2018 16:06:36 -0000
@@ -48,24 +48,24 @@ __RCSID("$NetBSD: adjtime.c,v 1.12 2011/
#include <sys/syscall.h>
#include <sys/clockctl.h>
-
-extern int __clockctl_fd;
+int clockctl_configure(void);
+int clockctl_is_configured(void);
int ____adjtime50(const struct timeval *, struct timeval *);
int
adjtime(const struct timeval *delta, struct timeval *olddelta)
{
struct clockctl_adjtime args;
- int rv;
+ int rv, clockctl = -1;
/*
- * we always attempt the syscall first and switch to
+ * we always attempt the syscall first and switch to
* clockctl if that fails with EPERM
*/
- if (__clockctl_fd == -1) {
+ if (!clockctl_is_configured()) {
rv = ____adjtime50(delta, olddelta);
-
+
/*
* try via clockctl if the call fails with EPERM
*/
@@ -76,19 +76,18 @@ adjtime(const struct timeval *delta, str
* If this fails, it means that we are not root
* and we cannot open clockctl. This is a failure.
*/
- __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
- if (__clockctl_fd == -1) {
+ if ((clockctl = clockctl_configure()) == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1;
}
}
- /*
- * If __clockctl_fd >=0, clockctl has already been open
+ /*
+ * If we're, clockctl has already been open
* and used, so we carry on using it.
*/
args.delta = delta;
args.olddelta = olddelta;
- return ioctl(__clockctl_fd, CLOCKCTL_ADJTIME, &args);
+ return ioctl(clockctl, CLOCKCTL_ADJTIME, &args);
}
Index: src/lib/libc/sys/ntp_adjtime.c
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/ntp_adjtime.c,v
retrieving revision 1.13
diff -p -u -u -r1.13 ntp_adjtime.c
--- src/lib/libc/sys/ntp_adjtime.c 20 Mar 2012 16:26:12 -0000 1.13
+++ src/lib/libc/sys/ntp_adjtime.c 29 Apr 2018 16:06:36 -0000
@@ -55,8 +55,8 @@ __RCSID("$NetBSD: ntp_adjtime.c,v 1.13 2
__weak_alias(ntp_adjtime,_ntp_adjtime)
#endif
-extern int __clockctl_fd;
-
+int clockctl_configure(void);
+int clockctl_is_configured(void);
int __ntp_adjtime(struct timex *);
int
@@ -64,7 +64,7 @@ ntp_adjtime(struct timex *tp)
{
struct clockctl_ntp_adjtime args;
int error;
- int rv;
+ int rv, clockctl = -1;
/*
* we always attempt to use the syscall unless we had to
@@ -72,9 +72,9 @@ ntp_adjtime(struct timex *tp)
*
* ntp_adjtime() is callable for mortals if tp->modes == 0 !
*/
- if (__clockctl_fd == -1) {
+ if (!clockctl_is_configured()) {
rv = __ntp_adjtime(tp);
-
+
/*
* if we fail with EPERM we try the clockctl device
*/
@@ -86,8 +86,7 @@ ntp_adjtime(struct timex *tp)
* and we cannot open clockctl. This is a true
* failure.
*/
- __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
- if (__clockctl_fd == -1) {
+ if ((clockctl = clockctl_configure()) == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1;
@@ -95,11 +94,11 @@ ntp_adjtime(struct timex *tp)
}
/*
- * If __clockctl_fd >=0, clockctl has already been open
+ * If we're, clockctl has already been open
* and used, so we carry on using it.
*/
args.tp = tp;
- error = ioctl(__clockctl_fd, CLOCKCTL_NTP_ADJTIME, &args);
+ error = ioctl(clockctl, CLOCKCTL_NTP_ADJTIME, &args);
/*
* There is no way to get retval set through ioctl(), hence we
Index: src/lib/libc/sys/settimeofday.c
===================================================================
RCS file: /cvsroot/src/lib/libc/sys/settimeofday.c,v
retrieving revision 1.14
diff -p -u -u -r1.14 settimeofday.c
--- src/lib/libc/sys/settimeofday.c 15 Oct 2011 23:00:02 -0000 1.14
+++ src/lib/libc/sys/settimeofday.c 29 Apr 2018 16:06:36 -0000
@@ -50,24 +50,45 @@ __RCSID("$NetBSD: settimeofday.c,v 1.14
#include <string.h>
#include <time.h>
#include <unistd.h>
-
-int __clockctl_fd = -1;
+static int __clockctl_fd = -1;
+
+int clockctl_configure(void);
+int clockctl_is_configured(void);
int ____settimeofday50(const struct timeval *, const void *);
int
+clockctl_configure(void)
+{
+
+ if (__clockctl_fd == -1) {
+ __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
+ /* XXX Check that __clockctl_fd is usable. */
+ }
+
+ return __clockctl_fd;
+}
+
+int
+clockctl_is_configured(void)
+{
+
+ return __clockctl_fd != -1;
+}
+
+int
settimeofday(const struct timeval *tv, const void *tzp)
{
struct clockctl_settimeofday args;
- int rv;
+ int rv, clockctl = -1;
/*
* try syscal first and attempt to switch to clockctl
* if that fails with EPERM
*/
- if (__clockctl_fd == -1) {
+ if (!clockctl_is_configured()) {
rv = ____settimeofday50(tv, tzp);
-
+
/*
* switch to clockctl if we fail with EPERM, this
* may be cause by an attempt to set the time backwards
@@ -77,19 +98,18 @@ settimeofday(const struct timeval *tv, c
if (rv != -1 || errno != EPERM)
return rv;
- __clockctl_fd = open(_PATH_CLOCKCTL, O_WRONLY | O_CLOEXEC, 0);
- if (__clockctl_fd == -1) {
+ if ((clockctl = clockctl_configure()) == -1) {
/* original error was EPERM - don't leak open errors */
errno = EPERM;
return -1;
}
}
- /*
- * If __clockctl_fd >=0, clockctl has already been open
+ /*
+ * If we're, clockctl has already been open
* and used, so we carry on using it.
*/
args.tv = tv;
args.tzp = tzp;
- return ioctl(__clockctl_fd, CLOCKCTL_SETTIMEOFDAY, &args);
+ return ioctl(clockctl, CLOCKCTL_SETTIMEOFDAY, &args);
}
Home |
Main Index |
Thread Index |
Old Index