From 3e18d701dea5599d1d4a2c4c9c481c52853cf644 Mon Sep 17 00:00:00 2001 From: Dmitry Chagin Date: Sun, 27 Dec 2015 15:37:07 +0000 Subject: [PATCH] Verify that tv_sec value specified in settimeofday() and clock_settime() (CLOCK_REALTIME case) system calls is non negative. This commit hides a kernel panic in atrtc_settime() as the clock_ts_to_ct() does not properly convert negative tv_sec. ps. in my opinion clock_ts_to_ct() should be rewritten to properly handle negative tv_sec values. Differential Revision: https://reviews.freebsd.org/D4714 Reviewed by: kib MFC after: 1 week --- lib/libc/sys/clock_gettime.2 | 4 +++- lib/libc/sys/gettimeofday.2 | 6 +++++- sys/kern/kern_time.c | 6 ++++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/lib/libc/sys/clock_gettime.2 b/lib/libc/sys/clock_gettime.2 index b42432f1dcd..e77b1e81dc3 100644 --- a/lib/libc/sys/clock_gettime.2 +++ b/lib/libc/sys/clock_gettime.2 @@ -29,7 +29,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 20, 2015 +.Dd December 27, 2015 .Dt CLOCK_GETTIME 2 .Os .Sh NAME @@ -134,6 +134,8 @@ The following error codes may be set in .It Bq Er EINVAL The .Fa clock_id +or +.Fa timespec argument was not a valid value. .It Bq Er EPERM diff --git a/lib/libc/sys/gettimeofday.2 b/lib/libc/sys/gettimeofday.2 index 888cbcd58e2..86b6b1aa193 100644 --- a/lib/libc/sys/gettimeofday.2 +++ b/lib/libc/sys/gettimeofday.2 @@ -28,7 +28,7 @@ .\" @(#)gettimeofday.2 8.2 (Berkeley) 5/26/95 .\" $FreeBSD$ .\" -.Dd December 20, 2015 +.Dd December 27, 2015 .Dt GETTIMEOFDAY 2 .Os .Sh NAME @@ -110,6 +110,10 @@ system call even when the system is secure. The following error codes may be set in .Va errno : .Bl -tag -width Er +.It Bq Er EINVAL +The supplied +.Fa timeval +value is invalid. .It Bq Er EPERM A user other than the super-user attempted to set the time. .El diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index 6ae0fb1a892..7705d9c976e 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -398,7 +398,8 @@ kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats) return (error); if (clock_id != CLOCK_REALTIME) return (EINVAL); - if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000) + if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 || + ats->tv_sec < 0) return (EINVAL); /* XXX Don't convert nsec->usec and back */ TIMESPEC_TO_TIMEVAL(&atv, ats); @@ -618,7 +619,8 @@ kern_settimeofday(struct thread *td, struct timeval *tv, struct timezone *tzp) return (error); /* Verify all parameters before changing time. */ if (tv) { - if (tv->tv_usec < 0 || tv->tv_usec >= 1000000) + if (tv->tv_usec < 0 || tv->tv_usec >= 1000000 || + tv->tv_sec < 0) return (EINVAL); error = settime(td, tv); }