Patch "[PATCH 109/135] time: Verify time values in adjtimex ADJ_SETOFFSET to" has been added to the 4.4-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
[PATCH 109/135] time: Verify time values in adjtimex ADJ_SETOFFSET to
to the 4.4-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
0109-time-Verify-time-values-in-adjtimex-ADJ_SETOFFSET-to.patch
and it can be found in the queue-4.4 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
2b189fe86b2820b583a80419ad3063b5f49fc007Mon Sep 17 00:00:00 2001
From: John Stultz <[email protected]>
Date: Thu, 3 Dec 2015 22:09:31 -0500
Subject: [PATCH 109/135] time: Verify time values in adjtimex ADJ_SETOFFSET to
avoid overflow
[ Upstream commit 37cf4dc3370fbca0344e23bb96446eb2c3548ba7 ]
For adjtimex()'s ADJ_SETOFFSET, make sure the tv_usec value is sane. We might multiply them later which can cause an overflow and undefined behavior.
This patch introduces new helper functions to simplify the checking code and adds comments to clarify
Orginally this patch was by Sasha Levin, but I've basically rewritten it, so he should get credit for finding the issue and I should get the blame for any mistakes made since.
Also, credit to Richard Cochran for the phrasing used in the comment for what is considered valid here.
--- include/linux/time.h | 26 ++++++++++++++++++++++++++ kernel/time/ntp.c | 10 ++++++++-- kernel/time/timekeeping.c | 2 +- 3 files changed, 35 insertions(+), 3 deletions(-)
include/linux/time.h +26 -0
@@ -125,6 +125,32 @@ static inline bool timeval_valid(const sextern struct timespec timespec_trunc (struct timespec t,unsigned gran); +/* +* Validates if a timespec/timeval used to inject a time offset is valid. +* Offsets can be postive or negative. The value of the timeval/timespec +* is the sum of its fields, but *NOTE*: the field tv_usec/tv_nsec must +* always be non-negative. +*/ +static inline bool timeval_inject_offset_valid (const struct timeval *tv) +{ +/* We don't check the tv_sec as it can be positive or negative */ + +/* Can't have more microseconds then a second */ +if (tv->tv_usec <0 || tv->tv_usec >=USEC_PER_SEC ) +return false; +return true; +} + +static inline bool timespec_inject_offset_valid (const struct timespec *ts) +{ +/* We don't check the tv_sec as it can be positive or negative */ + +/* Can't have more nanoseconds then a second */ +if (ts->tv_nsec <0 || ts->tv_nsec >=NSEC_PER_SEC ) +return false; +return true; +} +#define CURRENT_TIME (current_kernel_time())#define CURRENT_TIME_SEC ((struct timespec) { get_seconds(), 0 })
kernel/time/ntp.c +8 -2
@@ -674,8 +674,14 @@ int ntp_validate_timex(struct timex *txcreturn -EINVAL ; } -if ((txc->modes &ADJ_SETOFFSET ) && (!capable (CAP_SYS_TIME ))) -return -EPERM ; +if (txc->modes &ADJ_SETOFFSET ) { +/* In order to inject time, you gotta be super-user! */ +if (!capable (CAP_SYS_TIME )) +return -EPERM ; + +if (!timeval_inject_offset_valid (&txc->time)) +return -EINVAL ; + }/* * Check for potential multiplication overflows that can
kernel/time/timekeeping.c +1 -1
@@ -958,7 +958,7 @@ int timekeeping_inject_offset(struct timstruct timespec64 ts64, tmp;int ret =0 ; -if ((unsigned long )ts->tv_nsec >=NSEC_PER_SEC ) +if (!timespec_inject_offset_valid (ts))return -EINVAL ; ts64 =timespec_to_timespec64 (*ts);
Patches currently in stable-queue which might be from [email protected] are
queue-4.4/0110-ntp-Fix-ADJ_SETOFFSET-being-used-w-ADJ_NANO.patch queue-4.4/0109-time-Verify-time-values-in-adjtimex-ADJ_SETOFFSET-to.patch queue-4.4/0118-clocksource-Allow-unregistering-the-watchdog.patch