[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#1038451: bullseye-pu: package systemd/247.3-7+deb11u4



Package: release.debian.org
Severity: normal
Tags: bullseye
User: release.debian.org at packages.debian.org
Usertags: pu
X-Debbugs-CC: pkg-systemd-maintainers at lists.alioth.debian.org

Dear release team,

I have uploaded one new bugfix for systemd in bullseye. It is a
backport of two upstream patches to fix a calendar spec calculation
hang on DST change when TZ=Europe/Dublin as reported by Bullseye users
at #1033540.

The source debdiff is attached.

-- 
Kind regards,
Luca Boccassi
diff -Nru systemd-247.3/debian/changelog systemd-247.3/debian/changelog
--- systemd-247.3/debian/changelog	2023-04-30 13:56:31.000000000 +0100
+++ systemd-247.3/debian/changelog	2023-06-18 15:55:54.000000000 +0100
@@ -1,3 +1,10 @@
+systemd (247.3-7+deb11u4) bullseye; urgency=medium
+
+  * backport patches to fix a calendar spec calculation hang on DST change
+    if TZ=Europe/Dublin (Closes: #1033540)
+
+ -- Luca Boccassi <bluca@debian.org>  Sun, 18 Jun 2023 15:55:54 +0100
+
 systemd (247.3-7+deb11u3) bullseye; urgency=medium
 
   * udev: fix creating /dev/serial/by-id/ symlinks for USB devices.
diff -Nru systemd-247.3/debian/patches/series systemd-247.3/debian/patches/series
--- systemd-247.3/debian/patches/series	2023-04-30 13:51:17.000000000 +0100
+++ systemd-247.3/debian/patches/series	2023-06-18 15:55:16.000000000 +0100
@@ -37,6 +37,8 @@
 time-util-fix-buffer-over-run.patch
 machined-varlink-fix-double-free.patch
 Always-free-deserialized_subscribed-on-reload.patch
+shared-calendarspec-abort-calculation-after-1000-iteratio.patch
+shared-calendarspec-when-mktime-moves-us-backwards-jump-f.patch
 debian/Use-Debian-specific-config-files.patch
 debian/Bring-tmpfiles.d-tmp.conf-in-line-with-Debian-defaul.patch
 debian/Make-run-lock-tmpfs-an-API-fs.patch
diff -Nru systemd-247.3/debian/patches/shared-calendarspec-abort-calculation-after-1000-iteratio.patch systemd-247.3/debian/patches/shared-calendarspec-abort-calculation-after-1000-iteratio.patch
--- systemd-247.3/debian/patches/shared-calendarspec-abort-calculation-after-1000-iteratio.patch	1970-01-01 01:00:00.000000000 +0100
+++ systemd-247.3/debian/patches/shared-calendarspec-abort-calculation-after-1000-iteratio.patch	2023-06-18 15:55:16.000000000 +0100
@@ -0,0 +1,55 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Sun, 21 Mar 2021 20:59:32 +0100
+Subject: shared/calendarspec: abort calculation after 1000 iterations
+
+We have a bug where we seem to enter an infinite loop when running in the
+Europe/Dublin timezone. The timezone is "special" because it has negative SAVE
+values. The handling of this should obviously be fixed, but let's use a
+belt-and-suspenders approach, and gracefully fail if we fail to find an answer
+within a specific number of attempts. The code in this function is rather
+complex, and it's hard to rule out another bug in the future.
+
+(cherry picked from commit 169615c9a8cdc54d748d4dfc8279be9b3c2bec44)
+---
+ src/shared/calendarspec.c | 14 +++++++++++++-
+ 1 file changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
+index 7162592..80acc57 100644
+--- a/src/shared/calendarspec.c
++++ b/src/shared/calendarspec.c
+@@ -1211,6 +1211,10 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
+         return (weekdays_bits & (1 << k));
+ }
+ 
++/* A safety valve: if we get stuck in the calculation, return an error.
++ * C.f. https://bugzilla.redhat.com/show_bug.cgi?id=1941335. */
++#define MAX_CALENDAR_ITERATIONS 1000
++
+ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
+         struct tm c;
+         int tm_usec;
+@@ -1224,7 +1228,7 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
+         c = *tm;
+         tm_usec = *usec;
+ 
+-        for (;;) {
++        for (unsigned iteration = 0; iteration < MAX_CALENDAR_ITERATIONS; iteration++) {
+                 /* Normalize the current date */
+                 (void) mktime_or_timegm(&c, spec->utc);
+                 c.tm_isdst = spec->dst;
+@@ -1321,6 +1325,14 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) {
+                 *usec = tm_usec;
+                 return 0;
+         }
++
++        /* It seems we entered an infinite loop. Let's gracefully return an error instead of hanging or
++         * aborting. This code is also exercised when timers.target is brought up during early boot, so
++         * aborting here is problematic and hard to diagnose for users. */
++        _cleanup_free_ char *s = NULL;
++        (void) calendar_spec_to_string(spec, &s);
++        return log_warning_errno(SYNTHETIC_ERRNO(EDEADLK),
++                                 "Infinite loop in calendar calculation: %s", strna(s));
+ }
+ 
+ static int calendar_spec_next_usec_impl(const CalendarSpec *spec, usec_t usec, usec_t *ret_next) {
diff -Nru systemd-247.3/debian/patches/shared-calendarspec-when-mktime-moves-us-backwards-jump-f.patch systemd-247.3/debian/patches/shared-calendarspec-when-mktime-moves-us-backwards-jump-f.patch
--- systemd-247.3/debian/patches/shared-calendarspec-when-mktime-moves-us-backwards-jump-f.patch	1970-01-01 01:00:00.000000000 +0100
+++ systemd-247.3/debian/patches/shared-calendarspec-when-mktime-moves-us-backwards-jump-f.patch	2023-06-18 15:55:16.000000000 +0100
@@ -0,0 +1,105 @@
+From: =?utf-8?q?Zbigniew_J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
+Date: Mon, 22 Mar 2021 12:51:47 +0100
+Subject: shared/calendarspec: when mktime() moves us backwards, jump forward
+MIME-Version: 1.0
+Content-Type: text/plain; charset="utf-8"
+Content-Transfer-Encoding: 8bit
+
+When trying to calculate the next firing of 'Sun *-*-* 01:00:00', we'd fall
+into an infinite loop, because mktime() moves us "backwards":
+
+Before this patch:
+tm_within_bounds: good=0 2021-03-29 01:00:00 → 2021-03-29 00:00:00
+tm_within_bounds: good=0 2021-03-29 01:00:00 → 2021-03-29 00:00:00
+tm_within_bounds: good=0 2021-03-29 01:00:00 → 2021-03-29 00:00:00
+...
+
+We rely on mktime() normalizing the time. The man page does not say that it'll
+move the time forward, but our algorithm relies on this. So let's catch this
+case explicitly.
+
+With this patch:
+$ TZ=Europe/Dublin faketime 2021-03-21 build/systemd-analyze calendar --iterations=5 'Sun *-*-* 01:00:00'
+Normalized form: Sun *-*-* 01:00:00
+    Next elapse: Sun 2021-03-21 01:00:00 GMT
+       (in UTC): Sun 2021-03-21 01:00:00 UTC
+       From now: 59min left
+       Iter. #2: Sun 2021-04-04 01:00:00 IST
+       (in UTC): Sun 2021-04-04 00:00:00 UTC
+       From now: 1 weeks 6 days left           <---- note the 2 week jump here
+       Iter. #3: Sun 2021-04-11 01:00:00 IST
+       (in UTC): Sun 2021-04-11 00:00:00 UTC
+       From now: 2 weeks 6 days left
+       Iter. #4: Sun 2021-04-18 01:00:00 IST
+       (in UTC): Sun 2021-04-18 00:00:00 UTC
+       From now: 3 weeks 6 days left
+       Iter. #5: Sun 2021-04-25 01:00:00 IST
+       (in UTC): Sun 2021-04-25 00:00:00 UTC
+       From now: 1 months 4 days left
+
+Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1941335.
+
+(cherry picked from commit 129cb6e249bef30dc33e08f98f0b27a6de976f6f)
+---
+ src/shared/calendarspec.c    | 19 +++++++++++--------
+ src/test/test-calendarspec.c |  3 +++
+ test/test-functions          |  1 +
+ 3 files changed, 15 insertions(+), 8 deletions(-)
+
+diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c
+index 80acc57..c8d97c3 100644
+--- a/src/shared/calendarspec.c
++++ b/src/shared/calendarspec.c
+@@ -1185,15 +1185,18 @@ static int tm_within_bounds(struct tm *tm, bool utc) {
+                 return negative_errno();
+ 
+         /* Did any normalization take place? If so, it was out of bounds before */
+-        bool good = t.tm_year == tm->tm_year &&
+-                    t.tm_mon  == tm->tm_mon  &&
+-                    t.tm_mday == tm->tm_mday &&
+-                    t.tm_hour == tm->tm_hour &&
+-                    t.tm_min  == tm->tm_min  &&
+-                    t.tm_sec  == tm->tm_sec;
+-        if (!good)
++        int cmp = CMP(t.tm_year, tm->tm_year) ?:
++                  CMP(t.tm_mon, tm->tm_mon) ?:
++                  CMP(t.tm_mday, tm->tm_mday) ?:
++                  CMP(t.tm_hour, tm->tm_hour) ?:
++                  CMP(t.tm_min, tm->tm_min) ?:
++                  CMP(t.tm_sec, tm->tm_sec);
++
++        if (cmp < 0)
++                return -EDEADLK; /* Refuse to go backward */
++        if (cmp > 0)
+                 *tm = t;
+-        return good;
++        return cmp == 0;
+ }
+ 
+ static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) {
+diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c
+index e0b7f22..1b04186 100644
+--- a/src/test/test-calendarspec.c
++++ b/src/test/test-calendarspec.c
+@@ -218,6 +218,9 @@ int main(int argc, char* argv[]) {
+         // Confirm that timezones in the Spec work regardless of current timezone
+         test_next("2017-09-09 20:42:00 Pacific/Auckland", "", 12345, 1504946520000000);
+         test_next("2017-09-09 20:42:00 Pacific/Auckland", "EET", 12345, 1504946520000000);
++        /* Check that we don't start looping if mktime() moves us backwards */
++        test_next("Sun *-*-* 01:00:00 Europe/Dublin", "", 1616412478000000, 1617494400000000);
++        test_next("Sun *-*-* 01:00:00 Europe/Dublin", "IST", 1616412478000000, 1617494400000000);
+ 
+         assert_se(calendar_spec_from_string("test", &c) < 0);
+         assert_se(calendar_spec_from_string(" utc", &c) < 0);
+diff --git a/test/test-functions b/test/test-functions
+index 52b52bf..beaf4fa 100644
+--- a/test/test-functions
++++ b/test/test-functions
+@@ -1120,6 +1120,7 @@ install_zoneinfo() {
+     inst_any /usr/share/zoneinfo/Asia/Vladivostok
+     inst_any /usr/share/zoneinfo/Australia/Sydney
+     inst_any /usr/share/zoneinfo/Europe/Berlin
++    inst_any /usr/share/zoneinfo/Europe/Dublin
+     inst_any /usr/share/zoneinfo/Europe/Kiev
+     inst_any /usr/share/zoneinfo/Pacific/Auckland
+     inst_any /usr/share/zoneinfo/Pacific/Honolulu

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: