summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2020-07-15 21:20:09 +0000
committercheloha <cheloha@cvs.openbsd.org>2020-07-15 21:20:09 +0000
commit0df106c4dcbfa326b3ccb8225c296832cb5fd94e (patch)
tree1f5948a60b177ef4a8a1aaaecb8aa1a5425fc46a /sys/kern
parent6e4605ec4931a8c61e26e5ac8f8e8161ba21e72c (diff)
settimeofday(2): securelevel 2: prevent root from freezing the UTC clock
At securelevel 2 we prevent root from rewinding the kernel UTC clock. The rationale given in the comment is that this prevents a compromised root from setting arbitrary timestamps on files. I can't really speak to the efficacy of this mitigation, or to the efficacy of the securelevel concept in general, but the implementation of this mitigation is wrong. We need to check: timespeccmp(ts, &now, <=) instead of timespeccmp(ts, &now, <) like we do now. Time is a continuous value that is always advancing. We must prevent root from setting the kernel UTC clock to its current value in addition to prior values. Setting the UTC clock to its current value amounts to rewinding it even if we cannot actually measure the difference with a timespec. With this change, at securelevel 2, root can no longer completely freeze the UTC clock.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_time.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c
index 872480aa314..d5d02b0c670 100644
--- a/sys/kern/kern_time.c
+++ b/sys/kern/kern_time.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_time.c,v 1.132 2020/07/09 02:17:07 cheloha Exp $ */
+/* $OpenBSD: kern_time.c,v 1.133 2020/07/15 21:20:08 cheloha Exp $ */
/* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */
/*
@@ -91,7 +91,7 @@ settime(const struct timespec *ts)
* setting arbitrary time stamps on files.
*/
nanotime(&now);
- if (securelevel > 1 && timespeccmp(ts, &now, <)) {
+ if (securelevel > 1 && timespeccmp(ts, &now, <=)) {
printf("denied attempt to set clock back %lld seconds\n",
(long long)now.tv_sec - ts->tv_sec);
return (EPERM);