Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151144909
D27571.id80592.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D27571.id80592.diff
View Options
Index: sys/compat/freebsd32/freebsd32_misc.c
===================================================================
--- sys/compat/freebsd32/freebsd32_misc.c
+++ sys/compat/freebsd32/freebsd32_misc.c
@@ -2919,17 +2919,27 @@
freebsd32_clock_settime(struct thread *td,
struct freebsd32_clock_settime_args *uap)
{
- struct timespec ats;
- struct timespec32 ats32;
+ struct timespec ats, ots;
+ struct timespec32 ats32, ots32;
int error;
error = copyin(uap->tp, &ats32, sizeof(ats32));
- if (error)
+ if (error != 0)
return (error);
CP(ats32, ats, tv_sec);
CP(ats32, ats, tv_nsec);
- return (kern_clock_settime(td, uap->clock_id, &ats));
+ error = kern_clock_settime(td, uap->clock_id, &ats, &ots);
+ if (error != 0)
+ return (error);
+
+ if (uap->clock_id == CLOCK_ADJUST_REALTIME) {
+ CP(ots, ots32, tv_sec);
+ CP(ots, ots32, tv_nsec);
+ error = copyout(&ots32, __DECONST(void *, uap->tp),
+ sizeof(ots32));
+ }
+ return (error);
}
int
Index: sys/compat/linux/linux_time.c
===================================================================
--- sys/compat/linux/linux_time.c
+++ sys/compat/linux/linux_time.c
@@ -422,7 +422,7 @@
return (error);
}
- error = kern_clock_settime(td, nwhich, &ts);
+ error = kern_clock_settime(td, nwhich, &ts, NULL);
if (error != 0)
LIN_SDT_PROBE1(time, linux_clock_settime, settime_error, error);
Index: sys/dev/hyperv/utilities/vmbus_timesync.c
===================================================================
--- sys/dev/hyperv/utilities/vmbus_timesync.c
+++ sys/dev/hyperv/utilities/vmbus_timesync.c
@@ -132,7 +132,7 @@
}
hv_ts.tv_sec = hv_ns / NANOSEC;
hv_ts.tv_nsec = hv_ns % NANOSEC;
- kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts);
+ kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts, NULL);
/* Done! */
return;
}
@@ -164,7 +164,8 @@
}
hv_ts.tv_sec = hv_ns / NANOSEC;
hv_ts.tv_nsec = hv_ns % NANOSEC;
- kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts);
+ kern_clock_settime(curthread, CLOCK_REALTIME, &hv_ts,
+ NULL);
}
/* Done */
return;
Index: sys/kern/kern_tc.c
===================================================================
--- sys/kern/kern_tc.c
+++ sys/kern/kern_tc.c
@@ -1245,7 +1245,7 @@
* when we booted.
*/
void
-tc_setclock(struct timespec *ts)
+tc_setclock(struct timespec *ts, struct timespec *ots, bool abs)
{
struct timespec tbef, taft;
struct bintime bt, bt2;
@@ -1254,11 +1254,19 @@
nanotime(&tbef);
mtx_lock_spin(&tc_setclock_mtx);
cpu_tick_calibrate(1);
- binuptime(&bt2);
- bintime_sub(&bt, &bt2);
+ if (abs) {
+ binuptime(&bt2);
+ bintime_sub(&bt, &bt2);
+ }
- /* XXX fiddle all the little crinkly bits around the fiords... */
+ /*
+ * Fiddle all the little crinkly bits around the fiords...
+ * If requested, return the time after adjustment, under the
+ * tc_setclock spinlock to be as close to result as possible.
+ */
tc_windup(&bt);
+ if (ots != NULL)
+ getnanotime(ots);
mtx_unlock_spin(&tc_setclock_mtx);
/* Avoid rtc_generation == 0, since td_rtcgen == 0 is special. */
Index: sys/kern/kern_time.c
===================================================================
--- sys/kern/kern_time.c
+++ sys/kern/kern_time.c
@@ -86,6 +86,8 @@
*/
static int settime(struct thread *, struct timeval *);
+static int steptime(struct thread *, struct timeval *, struct timeval *,
+ bool abs);
static void timevalfix(struct timeval *);
static int user_clock_nanosleep(struct thread *td, clockid_t clock_id,
int flags, const struct timespec *ua_rqtp,
@@ -120,7 +122,6 @@
{
struct timeval delta, tv1, tv2;
static struct timeval maxtime, laststep;
- struct timespec ts;
microtime(&tv1);
delta = *tv;
@@ -161,10 +162,22 @@
}
}
+ return (steptime(td, tv, NULL, true));
+}
+
+static int
+steptime(struct thread *td, struct timeval *tv, struct timeval *otv, bool abs)
+{
+ struct timespec ts, ots;
+
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
- tc_setclock(&ts);
+ tc_setclock(&ts, &ots, abs);
resettodr();
+ if (otv != NULL) {
+ otv->tv_sec = ots.tv_sec;
+ otv->tv_usec = ots.tv_nsec / 1000;
+ }
return (0);
}
@@ -384,12 +397,17 @@
int
sys_clock_settime(struct thread *td, struct clock_settime_args *uap)
{
- struct timespec ats;
+ struct timespec ats, ots;
int error;
if ((error = copyin(uap->tp, &ats, sizeof(ats))) != 0)
return (error);
- return (kern_clock_settime(td, uap->clock_id, &ats));
+ error = kern_clock_settime(td, uap->clock_id, &ats, &ots);
+ if (error != 0)
+ return (error);
+ if (uap->clock_id == CLOCK_ADJUST_REALTIME)
+ error = copyout(&ots, __DECONST(void *, uap->tp), sizeof(ots));
+ return (error);
}
static int allow_insane_settime = 0;
@@ -397,26 +415,47 @@
&allow_insane_settime, 0,
"do not perform possibly restrictive checks on settime(2) args");
+/*
+ * Arbitrary limit to prevent insane
+ * clock_settime(CLOCK_ADJUST_REALTIME), e.g. with a garbage ts.
+ */
+#define CLOCK_ADJUST_REALTIME_LIMIT 3600
+
int
-kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats)
+kern_clock_settime(struct thread *td, clockid_t clock_id, struct timespec *ats,
+ struct timespec *ots)
{
- struct timeval atv;
+ struct timeval atv, oatv;
int error;
if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
return (error);
- if (clock_id != CLOCK_REALTIME)
- return (EINVAL);
- if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 ||
- ats->tv_sec < 0)
- return (EINVAL);
- if (!allow_insane_settime &&
- (ats->tv_sec > 8000ULL * 365 * 24 * 60 * 60 ||
- ats->tv_sec < utc_offset()))
- return (EINVAL);
- /* XXX Don't convert nsec->usec and back */
- TIMESPEC_TO_TIMEVAL(&atv, ats);
- error = settime(td, &atv);
+ error = EINVAL;
+ switch (clock_id) {
+ case CLOCK_ADJUST_REALTIME:
+ if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 ||
+ (!allow_insane_settime &&
+ (ats->tv_sec > CLOCK_ADJUST_REALTIME_LIMIT ||
+ ats->tv_sec < -CLOCK_ADJUST_REALTIME_LIMIT)))
+ break;
+ TIMESPEC_TO_TIMEVAL(&atv, ats);
+ error = steptime(td, &atv, &oatv, false);
+ if (ots != NULL)
+ TIMEVAL_TO_TIMESPEC(&oatv, ots);
+ break;
+ case CLOCK_REALTIME:
+ if (ats->tv_nsec < 0 || ats->tv_nsec >= 1000000000 ||
+ ats->tv_sec < 0)
+ break;
+ if (!allow_insane_settime &&
+ (ats->tv_sec > 8000ULL * 365 * 24 * 60 * 60 ||
+ ats->tv_sec < utc_offset()))
+ error = EINVAL;
+ /* XXX Don't convert nsec->usec and back */
+ TIMESPEC_TO_TIMEVAL(&atv, ats);
+ error = settime(td, &atv);
+ break;
+ }
return (error);
}
Index: sys/kern/subr_rtc.c
===================================================================
--- sys/kern/subr_rtc.c
+++ sys/kern/subr_rtc.c
@@ -361,7 +361,7 @@
}
if (ts.tv_sec >= 0) {
- tc_setclock(&ts);
+ tc_setclock(&ts, NULL, true);
#ifdef FFCLOCK
ffclock_reset_clock(&ts);
#endif
Index: sys/sys/syscallsubr.h
===================================================================
--- sys/sys/syscallsubr.h
+++ sys/sys/syscallsubr.h
@@ -105,7 +105,7 @@
int kern_clock_nanosleep(struct thread *td, clockid_t clock_id, int flags,
const struct timespec *rqtp, struct timespec *rmtp);
int kern_clock_settime(struct thread *td, clockid_t clock_id,
- struct timespec *ats);
+ struct timespec *ats, struct timespec *ots);
void kern_thread_cputime(struct thread *targettd, struct timespec *ats);
void kern_process_cputime(struct proc *targetp, struct timespec *ats);
int kern_close_range(struct thread *td, u_int lowfd, u_int highfd);
Index: sys/sys/time.h
===================================================================
--- sys/sys/time.h
+++ sys/sys/time.h
@@ -480,6 +480,7 @@
#define CLOCK_SECOND 13 /* FreeBSD-specific. */
#define CLOCK_THREAD_CPUTIME_ID 14
#define CLOCK_PROCESS_CPUTIME_ID 15
+#define CLOCK_ADJUST_REALTIME 16 /* FreeBSD-specific. */
#endif
#ifndef TIMER_ABSTIME
Index: sys/sys/timetc.h
===================================================================
--- sys/sys/timetc.h
+++ sys/sys/timetc.h
@@ -88,7 +88,7 @@
u_int64_t tc_getfrequency(void);
void tc_init(struct timecounter *tc);
-void tc_setclock(struct timespec *ts);
+void tc_setclock(struct timespec *ts, struct timespec *ots, bool abs);
void tc_ticktock(int cnt);
void cpu_tick_calibration(void);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Apr 7, 9:48 AM (10 h, 35 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31024158
Default Alt Text
D27571.id80592.diff (8 KB)
Attached To
Mode
D27571: CLOCK_ADJUST_REALTIME
Attached
Detach File
Event Timeline
Log In to Comment