summaryrefslogtreecommitdiff
path: root/sys/kern/kern_time.c
diff options
context:
space:
mode:
authorThorsten Lockert <tholo@cvs.openbsd.org>2004-07-28 17:15:13 +0000
committerThorsten Lockert <tholo@cvs.openbsd.org>2004-07-28 17:15:13 +0000
commitc65eb6dac1a01e8aedf3be76a030db86be9264f4 (patch)
treea775e61964a48db2019d60bb802076883a9b047b /sys/kern/kern_time.c
parent953666701c83d79c01d0ce862cd14f2120a66b7c (diff)
This touches only MI code, and adds new time keeping code. The
code is all conditionalized on __HAVE_TIMECOUNTER, and not enabled on any platforms. adjtime(2) support exists, courtesy of nordin@, sysctl(2) support and a concept of quality for each time source attached exists. High quality time sources exists for PIIX4 ACPI timer as well as some AMD power management chips. This will have to be redone once we actually add ACPI support (at that time we need to use the ACPI interfaces to get at these clocks). ok art@ ken@ miod@ jmc@ and many more
Diffstat (limited to 'sys/kern/kern_time.c')
-rw-r--r--sys/kern/kern_time.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index a19bf4c56a0..567341a2f85 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.44 2004/06/26 05:52:20 nordin Exp $ */
+/* $OpenBSD: kern_time.c,v 1.45 2004/07/28 17:15:12 tholo Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -39,6 +39,9 @@
#include <sys/proc.h>
#include <sys/vnode.h>
#include <sys/signalvar.h>
+#ifdef __HAVE_TIMECOUNTER
+#include <sys/timetc.h>
+#endif
#include <sys/mount.h>
#include <sys/syscallargs.h>
@@ -58,6 +61,49 @@ void itimerround(struct timeval *);
*/
/* This function is used by clock_settime and settimeofday */
+#ifdef __HAVE_TIMECOUNTER
+int
+settime(struct timespec *ts)
+{
+ struct timespec now;
+
+
+ /*
+ * Don't allow the time to be set forward so far it will wrap
+ * and become negative, thus allowing an attacker to bypass
+ * the next check below. The cutoff is 1 year before rollover
+ * occurs, so even if the attacker uses adjtime(2) to move
+ * the time past the cutoff, it will take a very long time
+ * to get to the wrap point.
+ *
+ * XXX: we check against INT_MAX since on 64-bit
+ * platforms, sizeof(int) != sizeof(long) and
+ * time_t is 32 bits even when atv.tv_sec is 64 bits.
+ */
+ if (ts->tv_sec > INT_MAX - 365*24*60*60) {
+ printf("denied attempt to set clock forward to %ld\n",
+ ts->tv_sec);
+ return (EPERM);
+ }
+ /*
+ * If the system is secure, we do not allow the time to be
+ * set to an earlier value (it may be slowed using adjtime,
+ * but not set back). This feature prevent interlopers from
+ * setting arbitrary time stamps on files.
+ */
+ nanotime(&now);
+ if (securelevel > 1 && timespeccmp(ts, &now, <)) {
+ printf("denied attempt to set clock back %ld seconds\n",
+ now.tv_sec - ts->tv_sec);
+ return (EPERM);
+ }
+
+ tc_setclock(ts);
+ resettodr();
+
+ return (0);
+}
+#else
int
settime(struct timespec *ts)
{
@@ -108,6 +154,7 @@ settime(struct timespec *ts)
return (0);
}
+#endif
/* ARGSUSED */
int
@@ -319,9 +366,13 @@ sys_settimeofday(p, v, retval)
return (0);
}
+#ifdef __HAVE_TIMECOUNTER
+struct timeval adjtimedelta; /* unapplied time correction */
+#else
int tickdelta; /* current clock skew, us. per tick */
long timedelta; /* unapplied time correction, us. */
long bigadj = 1000000; /* use 10x skew above bigadj us. */
+#endif
/* ARGSUSED */
int
@@ -334,6 +385,23 @@ sys_adjtime(p, v, retval)
syscallarg(const struct timeval *) delta;
syscallarg(struct timeval *) olddelta;
} */ *uap = v;
+#ifdef __HAVE_TIMECOUNTER
+ int error;
+
+ if ((error = suser(p, 0)))
+ return (error);
+
+ if (SCARG(uap, olddelta))
+ if ((error = copyout((void *)&adjtimedelta,
+ (void *)SCARG(uap, olddelta), sizeof(struct timeval))))
+ return (error);
+
+ if ((error = copyin((void *)SCARG(uap, delta), (void *)&adjtimedelta,
+ sizeof(struct timeval))))
+ return (error);
+
+ return (0);
+#else
struct timeval atv;
register long ndelta, ntickdelta, odelta;
int s, error;
@@ -380,6 +448,7 @@ sys_adjtime(p, v, retval)
return (error);
}
return (0);
+#endif
}
/*