diff --git a/util-linux-prevent-excessive-clock-drift-calculations.patch b/util-linux-prevent-excessive-clock-drift-calculations.patch new file mode 100644 index 0000000..9b7f359 --- /dev/null +++ b/util-linux-prevent-excessive-clock-drift-calculations.patch @@ -0,0 +1,162 @@ +From 654e902731ea15a3494a3831b78d2b9f1cd1408d Mon Sep 17 00:00:00 2001 +From: Ruediger Meier +Date: Fri, 16 May 2014 17:01:43 +0200 +Subject: [PATCH] Prevent excessive clock drift calculations + +Squashed commit of the following: + +commit f55b4b45126b657fe02f5f0d3d7fde740e6a6247 +Author: Karel Zak +Date: Tue May 6 12:51:42 2014 +0200 + + hwclock: fix typo + + Reported-by: Stanislav Brabec + Signed-off-by: Karel Zak + +commit db8fc5f37728810bdd5b865ac420c31714e35def +Author: Stanislav Brabec +Date: Mon May 5 20:49:49 2014 +0200 + + hwclock: Check drift value in /etc/adjtime + + Due to bug in older versions of hwclock, /etc/adjtime can contain + excessive drift value (up to many years per day). Prevent it + from applying. + + Signed-off-by: Stanislav Brabec + +commit f196fd1a5f8fff63635fd88b5a0f0bbc96978df2 +Author: Stanislav Brabec +Date: Mon May 5 20:49:29 2014 +0200 + + hwclock: Prevent excessive drift values + + Failure of CMOS battery can cause writing of excessive drift + values (up to many years per day). + + This causes excessive hwclock adjustment next time, which may lead + to overflow in calculate_adjustment() (and hang before 4a44a54b). + + Prevent this situation, check drift for limits and reset drift to zero + instead. + + Steps to reproduce: + + mv /etc/adjtime /etc/adjtime.backup + + rm /etc/adjtime + hwclock --set --date 2001-01-01\ 01:00:00 + + changing of /etc/adjtime. + mv /etc/adjtime /etc/adjtime.saved + hwclock --set --date 2001-01-02\ 01:00:01 + mv /etc/adjtime.saved /etc/adjtime + + echo "======= The /etc/adjtime has a \"correct\" look:" + cat /etc/adjtime + + hwclock --debug --systohc --utc + echo "======= The /etc/adjtime now has deeply failed drift value:" + cat /etc/adjtime + + mv /etc/adjtime /etc/adjtime.saved + hwclock --set --date 2015-01-01\ 01:00:00 + mv /etc/adjtime.saved /etc/adjtime + + hwclock --debug --adjust + echo "======= And the last /etc/adjtime:" + cat /etc/adjtime + + mv /etc/adjtime.backup /etc/adjtime + hwclock --systohc --utc + + Signed-off-by: Stanislav Brabec + +Signed-off-by: Ruediger Meier +--- + sys-utils/hwclock.c | 47 ++++++++++++++++++++++++++++++++++------------- + 1 file changed, 34 insertions(+), 13 deletions(-) + +diff --git a/sys-utils/hwclock.c b/sys-utils/hwclock.c +index 395b5c3..0abf01f 100644 +--- a/sys-utils/hwclock.c ++++ b/sys-utils/hwclock.c +@@ -91,6 +91,11 @@ struct clock_ops *ur; + + #define FLOOR(arg) ((arg >= 0 ? (int) arg : ((int) arg) - 1)); + ++/* Maximal clock adjustment in seconds per day. ++ (adjtime() glibc call has 2145 seconds limit on i386, so it is good enough for us as well, ++ 43219 is a maximal safe value preventing exact_adjustment overflow.) */ ++#define MAX_DRIFT 2145.0 ++ + const char *adj_file_name = NULL; + + struct adjtime { +@@ -1008,6 +1013,7 @@ adjust_drift_factor(struct adjtime *adjtime_p, + double adj_days, cal_days; + double exp_drift, unc_drift; + double factor_adjust; ++ double drift_factor; + + /* Adjusted time units per hardware time unit */ + atime_per_htime = 1.0 + adjtime_p->drift_factor / sec_per_day; +@@ -1033,16 +1039,28 @@ adjust_drift_factor(struct adjtime *adjtime_p, + /* Amount to add to previous drift factor */ + factor_adjust = unc_drift / cal_days; + +- if (debug) +- printf(_("Clock drifted %.1f seconds in the past " +- "%d seconds in spite of a drift factor of " +- "%f seconds/day.\n" +- "Adjusting drift factor by %f seconds/day\n"), +- unc_drift, +- (int)(nowtime - adjtime_p->last_calib_time), +- adjtime_p->drift_factor, factor_adjust); +- +- adjtime_p->drift_factor += factor_adjust; ++ /* New drift factor */ ++ drift_factor = adjtime_p->drift_factor + factor_adjust; ++ ++ if (abs(drift_factor) > MAX_DRIFT) { ++ if (debug) ++ printf(_("Clock drift factor was calculated as " ++ "%f seconds/day.\n" ++ "It is far too much. Resetting to zero.\n"), ++ drift_factor); ++ drift_factor = 0; ++ } else { ++ if (debug) ++ printf(_("Clock drifted %.1f seconds in the past " ++ "%d seconds in spite of a drift factor of " ++ "%f seconds/day.\n" ++ "Adjusting drift factor by %f seconds/day\n"), ++ unc_drift, ++ (int)(nowtime - adjtime_p->last_calib_time), ++ adjtime_p->drift_factor, factor_adjust); ++ } ++ ++ adjtime_p->drift_factor = drift_factor; + } + adjtime_p->last_calib_time = nowtime; + +@@ -1190,9 +1208,12 @@ do_adjustment(struct adjtime *adjtime_p, + adjtime_p->dirty = TRUE; + } else if (adjtime_p->last_adj_time == 0) { + if (debug) +- printf(_ +- ("Not setting clock because last adjustment time is zero, " +- "so history is bad.")); ++ printf(_("Not setting clock because last adjustment time is zero, " ++ "so history is bad.\n")); ++ } else if (abs(adjtime_p->drift_factor) > MAX_DRIFT) { ++ if (debug) ++ printf(_("Not setting clock because drift factor %f is far too high.\n"), ++ adjtime_p->drift_factor); + } else { + int adjustment; + /* Number of seconds we must insert in the Hardware Clock */ +-- +1.8.4.5 + diff --git a/util-linux.changes b/util-linux.changes index c093ba7..53a1411 100644 --- a/util-linux.changes +++ b/util-linux.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri May 16 15:10:53 UTC 2014 - sweet_f_a@gmx.de + +- Prevent excessive clock drift calculations (bnc#871698, + util-linux-prevent-excessive-clock-drift-calculations.patch), + committed by sbrabec@suse.cz + ------------------------------------------------------------------- Thu May 8 08:15:04 UTC 2014 - werner@suse.de diff --git a/util-linux.spec b/util-linux.spec index 1ceba6d..2373d3a 100644 --- a/util-linux.spec +++ b/util-linux.spec @@ -128,6 +128,8 @@ Patch30: blkid-stop-scanning-on-I-O-error.patch Patch31: blkid-convert-superblocks-to-new-calling-convention.patch # PATH-FIX-UPSTREAM util-linux-libblkid-ext-probe.patch bnc864703 sbrabec@suse.cz -- libblkid: Drop the broken ext2/ext3/ext4 discrimination logic. Patch32: util-linux-libblkid-ext-probe.patch +# PATCH-FIX-UPSTREAM bnc871698 sbrabec@suse.cz +Patch33: util-linux-prevent-excessive-clock-drift-calculations.patch ## ## klogconsole @@ -263,6 +265,7 @@ xzcat %{S:0} | %gpg_verify %{S:12} - %patch30 -p1 %patch31 -p1 %patch32 -p1 +%patch33 -p1 # # setctsid cp -p %{S:22} %{S:23} .