Blame SOURCES/0001-netfilter-xt_time-use-time64_t.patch

Kmods SIG 0e2548
From fcbad8293d52864d87d0b9f6035fd87a049d59d8 Mon Sep 17 00:00:00 2001
Kmods SIG 0e2548
From: Arnd Bergmann <arnd@arndb.de>
Kmods SIG 0e2548
Date: Fri, 8 Nov 2019 21:34:28 +0100
Kmods SIG 0e2548
Subject: [Backport fcbad8293d52] netfilter: xt_time: use time64_t
Kmods SIG 0e2548
Kmods SIG 0e2548
The current xt_time driver suffers from the y2038 overflow on 32-bit
Kmods SIG 0e2548
architectures, when the time of day calculations break.
Kmods SIG 0e2548
Kmods SIG 0e2548
Also, on both 32-bit and 64-bit architectures, there is a problem with
Kmods SIG 0e2548
info->date_start/stop, which is part of the user ABI and overflows in
Kmods SIG 0e2548
in 2106.
Kmods SIG 0e2548
Kmods SIG 0e2548
Fix the first issue by using time64_t and explicit calls to div_u64()
Kmods SIG 0e2548
and div_u64_rem(), and document the seconds issue.
Kmods SIG 0e2548
Kmods SIG 0e2548
The explicit 64-bit division is unfortunately slower on 32-bit
Kmods SIG 0e2548
architectures, but doing it as unsigned lets us use the optimized
Kmods SIG 0e2548
division-through-multiplication path in most configurations.  This should
Kmods SIG 0e2548
be fine, as the code already does not allow any negative time of day
Kmods SIG 0e2548
values.
Kmods SIG 0e2548
Kmods SIG 0e2548
Using u32 seconds values consistently would probably also work and
Kmods SIG 0e2548
be a little more efficient, but that doesn't feel right as it would
Kmods SIG 0e2548
propagate the y2106 overflow to more place rather than fewer.
Kmods SIG 0e2548
Kmods SIG 0e2548
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Kmods SIG 0e2548
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Kmods SIG 0e2548
---
Kmods SIG 0e2548
 src/xt_time.c | 19 +++++++++++--------
Kmods SIG 0e2548
 1 file changed, 11 insertions(+), 8 deletions(-)
Kmods SIG 0e2548
Kmods SIG 0e2548
diff --git a/src/xt_time.c b/src/xt_time.c
Kmods SIG 0e2548
index 8dbb4d48f2ed5995dedaa8eb4f4b18a0ba91acb2..67cb984894153d5db895e104adacf51422926e34 100644
Kmods SIG 0e2548
--- a/src/xt_time.c
Kmods SIG 0e2548
+++ b/src/xt_time.c
Kmods SIG 0e2548
@@ -77,12 +77,12 @@ static inline bool is_leap(unsigned int y)
Kmods SIG 0e2548
  * This is done in three separate functions so that the most expensive
Kmods SIG 0e2548
  * calculations are done last, in case a "simple match" can be found earlier.
Kmods SIG 0e2548
  */
Kmods SIG 0e2548
-static inline unsigned int localtime_1(struct xtm *r, time_t time)
Kmods SIG 0e2548
+static inline unsigned int localtime_1(struct xtm *r, time64_t time)
Kmods SIG 0e2548
 {
Kmods SIG 0e2548
 	unsigned int v, w;
Kmods SIG 0e2548
 
Kmods SIG 0e2548
 	/* Each day has 86400s, so finding the hour/minute is actually easy. */
Kmods SIG 0e2548
-	v         = time % SECONDS_PER_DAY;
Kmods SIG 0e2548
+	div_u64_rem(time, SECONDS_PER_DAY, &v);
Kmods SIG 0e2548
 	r->second = v % 60;
Kmods SIG 0e2548
 	w         = v / 60;
Kmods SIG 0e2548
 	r->minute = w % 60;
Kmods SIG 0e2548
@@ -90,13 +90,13 @@ static inline unsigned int localtime_1(struct xtm *r, time_t time)
Kmods SIG 0e2548
 	return v;
Kmods SIG 0e2548
 }
Kmods SIG 0e2548
 
Kmods SIG 0e2548
-static inline void localtime_2(struct xtm *r, time_t time)
Kmods SIG 0e2548
+static inline void localtime_2(struct xtm *r, time64_t time)
Kmods SIG 0e2548
 {
Kmods SIG 0e2548
 	/*
Kmods SIG 0e2548
 	 * Here comes the rest (weekday, monthday). First, divide the SSTE
Kmods SIG 0e2548
 	 * by seconds-per-day to get the number of _days_ since the epoch.
Kmods SIG 0e2548
 	 */
Kmods SIG 0e2548
-	r->dse = time / 86400;
Kmods SIG 0e2548
+	r->dse = div_u64(time, SECONDS_PER_DAY);
Kmods SIG 0e2548
 
Kmods SIG 0e2548
 	/*
Kmods SIG 0e2548
 	 * 1970-01-01 (w=0) was a Thursday (4).
Kmods SIG 0e2548
@@ -105,7 +105,7 @@ static inline void localtime_2(struct xtm *r, time_t time)
Kmods SIG 0e2548
 	r->weekday = (4 + r->dse - 1) % 7 + 1;
Kmods SIG 0e2548
 }
Kmods SIG 0e2548
 
Kmods SIG 0e2548
-static void localtime_3(struct xtm *r, time_t time)
Kmods SIG 0e2548
+static void localtime_3(struct xtm *r, time64_t time)
Kmods SIG 0e2548
 {
Kmods SIG 0e2548
 	unsigned int year, i, w = r->dse;
Kmods SIG 0e2548
 
Kmods SIG 0e2548
@@ -160,7 +160,7 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
Kmods SIG 0e2548
 	const struct xt_time_info *info = par->matchinfo;
Kmods SIG 0e2548
 	unsigned int packet_time;
Kmods SIG 0e2548
 	struct xtm current_time;
Kmods SIG 0e2548
-	s64 stamp;
Kmods SIG 0e2548
+	time64_t stamp;
Kmods SIG 0e2548
 
Kmods SIG 0e2548
 	/*
Kmods SIG 0e2548
 	 * We need real time here, but we can neither use skb->tstamp
Kmods SIG 0e2548
@@ -173,14 +173,14 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
Kmods SIG 0e2548
 	 *	1. match before 13:00
Kmods SIG 0e2548
 	 *	2. match after 13:00
Kmods SIG 0e2548
 	 *
Kmods SIG 0e2548
-	 * If you match against processing time (get_seconds) it
Kmods SIG 0e2548
+	 * If you match against processing time (ktime_get_real_seconds) it
Kmods SIG 0e2548
 	 * may happen that the same packet matches both rules if
Kmods SIG 0e2548
 	 * it arrived at the right moment before 13:00, so it would be
Kmods SIG 0e2548
 	 * better to check skb->tstamp and set it via __net_timestamp()
Kmods SIG 0e2548
 	 * if needed.  This however breaks outgoing packets tx timestamp,
Kmods SIG 0e2548
 	 * and causes them to get delayed forever by fq packet scheduler.
Kmods SIG 0e2548
 	 */
Kmods SIG 0e2548
-	stamp = get_seconds();
Kmods SIG 0e2548
+	stamp = ktime_get_real_seconds();
Kmods SIG 0e2548
 
Kmods SIG 0e2548
 	if (info->flags & XT_TIME_LOCAL_TZ)
Kmods SIG 0e2548
 		/* Adjust for local timezone */
Kmods SIG 0e2548
@@ -193,6 +193,9 @@ time_mt(const struct sk_buff *skb, struct xt_action_param *par)
Kmods SIG 0e2548
 	 *   - 'now' is in the weekday mask
Kmods SIG 0e2548
 	 *   - 'now' is in the daytime range time_start..time_end
Kmods SIG 0e2548
 	 * (and by default, libxt_time will set these so as to match)
Kmods SIG 0e2548
+	 *
Kmods SIG 0e2548
+	 * note: info->date_start/stop are unsigned 32-bit values that
Kmods SIG 0e2548
+	 *	 can hold values beyond y2038, but not after y2106.
Kmods SIG 0e2548
 	 */
Kmods SIG 0e2548
 
Kmods SIG 0e2548
 	if (stamp < info->date_start || stamp > info->date_stop)
Kmods SIG 0e2548
-- 
Kmods SIG 0e2548
2.31.1
Kmods SIG 0e2548