From cc11d1e0e26476398d62e606c1f3e76c228e2105 Mon Sep 17 00:00:00 2001 From: DistroBaker Date: Wed, 24 Mar 2021 22:35:23 +0000 Subject: [PATCH] Merged update from upstream sources This is an automated DistroBaker update from upstream sources. If you do not know what this is about or would like to opt out, contact the OSCI team. Source: https://src.fedoraproject.org/rpms/systemd.git#9bbbaa81972523606e7c99490e0fb2c839e30f2a --- ...-do-not-use-epoll_pwait2-tentatively.patch | 35 -- ...7eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch | 36 ++ 19075.patch | 415 ++++++++++++++++++ 19079.patch | 178 ++++++++ 19080.patch | 67 +++ ...3f70ebe035323f4f079028a262669a2bbbf6.patch | 55 +++ ...afae96c72564cd4cd766555845f17e3c12a9.patch | 85 ++++ systemd.spec | 33 +- 8 files changed, 864 insertions(+), 40 deletions(-) delete mode 100644 0001-sd-event-do-not-use-epoll_pwait2-tentatively.patch create mode 100644 0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch create mode 100644 19075.patch create mode 100644 19079.patch create mode 100644 19080.patch create mode 100644 5cdb3f70ebe035323f4f079028a262669a2bbbf6.patch create mode 100644 f9b3afae96c72564cd4cd766555845f17e3c12a9.patch diff --git a/0001-sd-event-do-not-use-epoll_pwait2-tentatively.patch b/0001-sd-event-do-not-use-epoll_pwait2-tentatively.patch deleted file mode 100644 index 4baf338..0000000 --- a/0001-sd-event-do-not-use-epoll_pwait2-tentatively.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 829e2b5cd552c5ea33a8ccc43e118ba87bbda206 Mon Sep 17 00:00:00 2001 -From: Yu Watanabe -Date: Fri, 19 Mar 2021 04:13:59 +0900 -Subject: [PATCH] sd-event: do not use epoll_pwait2() tentatively - ---- - src/libsystemd/sd-event/sd-event.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c -index 8f74b14101..14bed4f854 100644 ---- a/src/libsystemd/sd-event/sd-event.c -+++ b/src/libsystemd/sd-event/sd-event.c -@@ -3808,8 +3808,9 @@ static int epoll_wait_usec( - int maxevents, - usec_t timeout) { - -- static bool epoll_pwait2_absent = false; - int r, msec; -+#if 0 -+ static bool epoll_pwait2_absent = false; - - /* A wrapper that uses epoll_pwait2() if available, and falls back to epoll_wait() if not */ - -@@ -3829,6 +3830,7 @@ static int epoll_wait_usec( - - epoll_pwait2_absent = true; - } -+#endif - - if (timeout == USEC_INFINITY) - msec = -1; --- -2.30.2 - diff --git a/0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch b/0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch new file mode 100644 index 0000000..5c5317f --- /dev/null +++ b/0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch @@ -0,0 +1,36 @@ +From 0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d Mon Sep 17 00:00:00 2001 +From: Sergey Bugaev +Date: Mon, 22 Mar 2021 18:31:12 +0300 +Subject: [PATCH] log: protect errno in log_open() + +Commit 0b1f3c768ce1bd1490a5e53f539976dcef8ca765 has introduced log_open() +calls after exec fails post-fork. However, the log_open() call itself could +change the value of errno, which, for me, manifested in: + +$ coredumpctl gdb +... +Failed to invoke gdb: Success + +Fix this by using PROTECT_ERRNO in log_open(). +--- + src/basic/log.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/basic/log.c b/src/basic/log.c +index c8cca96bca4..0e6023cff22 100644 +--- a/src/basic/log.c ++++ b/src/basic/log.c +@@ -252,6 +252,13 @@ int log_open(void) { + + /* Do not call from library code. */ + ++ /* This function is often called in preparation for being able ++ * to log. Let's make sure we don't clobber errno, so that a call ++ * to a logging function immediately following a log_open() call ++ * can still easily reference an error that happened immediately ++ * before the log_open() call. */ ++ PROTECT_ERRNO; ++ + /* If we don't use the console we close it here, to not get + * killed by SAK. If we don't use syslog we close it here so + * that we are not confused by somebody deleting the socket in diff --git a/19075.patch b/19075.patch new file mode 100644 index 0000000..10f391e --- /dev/null +++ b/19075.patch @@ -0,0 +1,415 @@ +From 169615c9a8cdc54d748d4dfc8279be9b3c2bec44 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 21 Mar 2021 20:59:32 +0100 +Subject: [PATCH 1/5] 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. +--- + 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 4f68a570b52..feb43efdcda 100644 +--- a/src/shared/calendarspec.c ++++ b/src/shared/calendarspec.c +@@ -1210,6 +1210,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; +@@ -1223,7 +1227,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; +@@ -1320,6 +1324,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) { + +From 462f15d92d35f812d7d77edd486ca63236cffe83 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 22 Mar 2021 09:20:47 +0100 +Subject: [PATCH 2/5] shared/calendarspec: constify parameter and simplify + assignments to variable + +The scope of start & stop is narrowed down, and they are assigned only once. +No functional change, but I think the code is easier to read this way. +Also add a comment to make the code easier to read. +--- + src/shared/calendarspec.c | 33 ++++++++++++++++++++++----------- + 1 file changed, 22 insertions(+), 11 deletions(-) + +diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c +index feb43efdcda..5c666412946 100644 +--- a/src/shared/calendarspec.c ++++ b/src/shared/calendarspec.c +@@ -1101,7 +1101,7 @@ int calendar_spec_from_string(const char *p, CalendarSpec **spec) { + return 0; + } + +-static int find_end_of_month(struct tm *tm, bool utc, int day) { ++static int find_end_of_month(const struct tm *tm, bool utc, int day) { + struct tm t = *tm; + + t.tm_mon++; +@@ -1114,28 +1114,39 @@ static int find_end_of_month(struct tm *tm, bool utc, int day) { + return t.tm_mday; + } + +-static int find_matching_component(const CalendarSpec *spec, const CalendarComponent *c, +- struct tm *tm, int *val) { +- const CalendarComponent *p = c; +- int start, stop, d = -1; ++static int find_matching_component( ++ const CalendarSpec *spec, ++ const CalendarComponent *c, ++ const struct tm *tm, /* tm is only used for end-of-month calculations */ ++ int *val) { ++ ++ int d = -1, r; + bool d_set = false; +- int r; + + assert(val); + ++ /* Finds the *earliest* matching time specified by one of the CalendarCompoment items in chain c. ++ * If no matches can be found, returns -ENOENT. ++ * Otherwise, updates *val to the matching time. 1 is returned if *val was changed, 0 otherwise. ++ */ ++ + if (!c) + return 0; + ++ bool end_of_month = spec->end_of_month && c == spec->day; ++ + while (c) { +- start = c->start; +- stop = c->stop; ++ int start, stop; + +- if (spec->end_of_month && p == spec->day) { +- start = find_end_of_month(tm, spec->utc, start); +- stop = find_end_of_month(tm, spec->utc, stop); ++ if (end_of_month) { ++ start = find_end_of_month(tm, spec->utc, c->start); ++ stop = find_end_of_month(tm, spec->utc, c->stop); + + if (stop > 0) + SWAP_TWO(start, stop); ++ } else { ++ start = c->start; ++ stop = c->stop; + } + + if (start >= *val) { + +From f035bb1b7a5900439640f267db881c60d042e450 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 22 Mar 2021 11:10:22 +0100 +Subject: [PATCH 3/5] test-calendarspec: print offending line in output + +The output is rather long at this makes it easier to jump to the right place. +Also use normal output routines and set_unset_env() to make things more +compact. +--- + src/test/test-calendarspec.c | 48 +++++++++++++++++------------------- + 1 file changed, 22 insertions(+), 26 deletions(-) + +diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c +index 01ec7f87704..152ce879f8a 100644 +--- a/src/test/test-calendarspec.c ++++ b/src/test/test-calendarspec.c +@@ -2,11 +2,11 @@ + + #include "alloc-util.h" + #include "calendarspec.h" ++#include "env-util.h" + #include "errno-util.h" + #include "string-util.h" +-#include "util.h" + +-static void test_one(const char *input, const char *output) { ++static void _test_one(int line, const char *input, const char *output) { + CalendarSpec *c; + _cleanup_free_ char *p = NULL, *q = NULL; + usec_t u; +@@ -16,13 +16,13 @@ static void test_one(const char *input, const char *output) { + assert_se(calendar_spec_from_string(input, &c) >= 0); + + assert_se(calendar_spec_to_string(c, &p) >= 0); +- printf("\"%s\" → \"%s\"\n", input, p); ++ log_info("line %d: \"%s\" → \"%s\"", line, input, p); + + assert_se(streq(p, output)); + + u = now(CLOCK_REALTIME); + r = calendar_spec_next_usec(c, u, &u); +- printf("Next: %s\n", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof(buf), u)); ++ log_info("Next: %s", r < 0 ? strerror_safe(r) : format_timestamp(buf, sizeof buf, u)); + calendar_spec_free(c); + + assert_se(calendar_spec_from_string(p, &c) >= 0); +@@ -31,8 +31,9 @@ static void test_one(const char *input, const char *output) { + + assert_se(streq(q, p)); + } ++#define test_one(input, output) _test_one(__LINE__, input, output) + +-static void test_next(const char *input, const char *new_tz, usec_t after, usec_t expect) { ++static void _test_next(int line, const char *input, const char *new_tz, usec_t after, usec_t expect) { + CalendarSpec *c; + usec_t u; + char *old_tz; +@@ -43,22 +44,19 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ + if (old_tz) + old_tz = strdupa(old_tz); + +- if (new_tz) { +- char *colon_tz; ++ if (new_tz) ++ new_tz = strjoina(":", new_tz); + +- colon_tz = strjoina(":", new_tz); +- assert_se(setenv("TZ", colon_tz, 1) >= 0); +- } else +- assert_se(unsetenv("TZ") >= 0); ++ assert_se(set_unset_env("TZ", new_tz, true) == 0); + tzset(); + + assert_se(calendar_spec_from_string(input, &c) >= 0); + +- printf("\"%s\"\n", input); ++ log_info("line %d: \"%s\" new_tz=%s", line, input, strnull(new_tz)); + + u = after; + r = calendar_spec_next_usec(c, after, &u); +- printf("At: %s\n", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US)); ++ log_info("At: %s", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US)); + if (expect != USEC_INFINITY) + assert_se(r >= 0 && u == expect); + else +@@ -66,12 +64,10 @@ static void test_next(const char *input, const char *new_tz, usec_t after, usec_ + + calendar_spec_free(c); + +- if (old_tz) +- assert_se(setenv("TZ", old_tz, 1) >= 0); +- else +- assert_se(unsetenv("TZ") >= 0); ++ assert_se(set_unset_env("TZ", old_tz, true) == 0); + tzset(); + } ++#define test_next(input, new_tz, after, expect) _test_next(__LINE__, input,new_tz,after,expect) + + static void test_timestamp(void) { + char buf[FORMAT_TIMESTAMP_MAX]; +@@ -83,12 +79,12 @@ static void test_timestamp(void) { + + x = now(CLOCK_REALTIME); + +- assert_se(format_timestamp_style(buf, sizeof(buf), x, TIMESTAMP_US)); +- printf("%s\n", buf); ++ assert_se(format_timestamp_style(buf, sizeof buf, x, TIMESTAMP_US)); ++ log_info("%s", buf); + assert_se(calendar_spec_from_string(buf, &c) >= 0); + assert_se(calendar_spec_to_string(c, &t) >= 0); + calendar_spec_free(c); +- printf("%s\n", t); ++ log_info("%s", t); + + assert_se(parse_timestamp(t, &y) >= 0); + assert_se(y == x); +@@ -104,11 +100,11 @@ static void test_hourly_bug_4031(void) { + n = now(CLOCK_REALTIME); + assert_se((r = calendar_spec_next_usec(c, n, &u)) >= 0); + +- printf("Now: %s (%"PRIu64")\n", format_timestamp_style(buf, sizeof buf, n, TIMESTAMP_US), n); +- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US), u); ++ log_info("Now: %s (%"PRIu64")", format_timestamp_style(buf, sizeof buf, n, TIMESTAMP_US), n); ++ log_info("Next hourly: %s (%"PRIu64")", r < 0 ? strerror_safe(r) : format_timestamp_style(buf, sizeof buf, u, TIMESTAMP_US), u); + + assert_se((r = calendar_spec_next_usec(c, u, &w)) >= 0); +- printf("Next hourly: %s (%"PRIu64")\n", r < 0 ? strerror_safe(r) : format_timestamp_style(zaf, sizeof zaf, w, TIMESTAMP_US), w); ++ log_info("Next hourly: %s (%"PRIu64")", r < 0 ? strerror_safe(r) : format_timestamp_style(zaf, sizeof zaf, w, TIMESTAMP_US), w); + + assert_se(n < u); + assert_se(u <= n + USEC_PER_HOUR); +@@ -209,13 +205,13 @@ int main(int argc, char* argv[]) { + test_next("2017-08-06 9..17/2:00 UTC", "", 1502029800000000, 1502031600000000); + test_next("2016-12-* 3..21/6:00 UTC", "", 1482613200000001, 1482634800000000); + test_next("2017-09-24 03:30:00 Pacific/Auckland", "", 12345, 1506177000000000); +- // Due to daylight saving time - 2017-09-24 02:30:00 does not exist ++ /* Due to daylight saving time - 2017-09-24 02:30:00 does not exist */ + test_next("2017-09-24 02:30:00 Pacific/Auckland", "", 12345, -1); + test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 12345, 1491053400000000); +- // Confirm that even though it's a time change here (backward) 02:30 happens only once ++ /* Confirm that even though it's a time change here (backward) 02:30 happens only once */ + test_next("2017-04-02 02:30:00 Pacific/Auckland", "", 1491053400000000, -1); + test_next("2017-04-02 03:30:00 Pacific/Auckland", "", 12345, 1491060600000000); +- // Confirm that timezones in the Spec work regardless of current timezone ++ /* 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); + + +From 47b0b65766229a18921a3ce831ef708ef408a34c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 22 Mar 2021 11:29:35 +0100 +Subject: [PATCH 4/5] test-calendarspec: do not convert timezone "" to ":" + +I *think* it doesn't actually make any difference, because ":" will be ignored. +437f48a471f51ac9dd2697ee3b848a71b4f101df added prefixing with ":", but didn't +take into account the fact that we also use "" with a different meaning than +NULL here. But let's restore the original behaviour of specifying the empty +string. +--- + src/test/test-calendarspec.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c +index 152ce879f8a..c62e6860cf9 100644 +--- a/src/test/test-calendarspec.c ++++ b/src/test/test-calendarspec.c +@@ -44,7 +44,7 @@ static void _test_next(int line, const char *input, const char *new_tz, usec_t a + if (old_tz) + old_tz = strdupa(old_tz); + +- if (new_tz) ++ if (!isempty(new_tz)) + new_tz = strjoina(":", new_tz); + + assert_se(set_unset_env("TZ", new_tz, true) == 0); + +From 129cb6e249bef30dc33e08f98f0b27a6de976f6f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 22 Mar 2021 12:51:47 +0100 +Subject: [PATCH 5/5] 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. +--- + 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 5c666412946..bf24d8d5bbb 100644 +--- a/src/shared/calendarspec.c ++++ b/src/shared/calendarspec.c +@@ -1195,15 +1195,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 c62e6860cf9..4f1d0f64d57 100644 +--- a/src/test/test-calendarspec.c ++++ b/src/test/test-calendarspec.c +@@ -214,6 +214,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 d7f7967e2ff..6b94058fd36 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -1340,6 +1340,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 diff --git a/19079.patch b/19079.patch new file mode 100644 index 0000000..0f5c23e --- /dev/null +++ b/19079.patch @@ -0,0 +1,178 @@ +From 4cba52cc7a2191d0b38e605801c60d8648bc67e2 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 22 Mar 2021 18:27:36 +0100 +Subject: [PATCH 1/2] resolved: propagate correct error variable + +--- + src/resolve/resolved-dns-query.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c +index e4386c402ac..c5805111d21 100644 +--- a/src/resolve/resolved-dns-query.c ++++ b/src/resolve/resolved-dns-query.c +@@ -982,12 +982,12 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) + r = dns_question_cname_redirect(q->question_idna, cname, &nq_idna); + if (r < 0) + return r; +- else if (r > 0) ++ if (r > 0) + log_debug("Following CNAME/DNAME %s → %s.", dns_question_first_name(q->question_idna), dns_question_first_name(nq_idna)); + + k = dns_question_is_equal(q->question_idna, q->question_utf8); + if (k < 0) +- return r; ++ return k; + if (k > 0) { + /* Same question? Shortcut new question generation */ + nq_utf8 = dns_question_ref(nq_idna); +@@ -996,7 +996,7 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname) + k = dns_question_cname_redirect(q->question_utf8, cname, &nq_utf8); + if (k < 0) + return k; +- else if (k > 0) ++ if (k > 0) + log_debug("Following UTF8 CNAME/DNAME %s → %s.", dns_question_first_name(q->question_utf8), dns_question_first_name(nq_utf8)); + } + + +From 1a71fe4ee5248140f2395a7daedfad8f8b9ad291 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 22 Mar 2021 18:27:46 +0100 +Subject: [PATCH 2/2] resolved: don't accept responses to query unless they + completely answer our questions + +When we checking if the responses we collected for a DnsQuery are +sufficient to complete it we previously only check if one of the +collected response RRs matches at least one of the question RR keys. + +This changes the logic to require that there must be at least one +response RR matched *each* of the question RR keys before considering +the answer complete. + +Otherwise we might end up accepting an A reply as complete answer for an +A/AAAA query and vice versa, but we want to make sure we wait until we +get a reply on both types before returning this to the user in all +cases. + +This has been broken for basically forever, but didn't surface until +b1eea703e01da1e280e179fb119449436a0c9b8e since until then we'd basically +ignore the auxiliary RRs included in CNAME/DNAME replies. Once that +commit was made we'd start using the auxiliary RRs included in +CNAME/DNAME replies but those typically included only A or only AAAA +which we then took for complete. + +Fixe: #19049 +--- + src/resolve/resolved-dns-query.c | 55 ++++++++++++++++++++++++++++---- + src/resolve/resolved-dns-query.h | 9 +++++- + 2 files changed, 56 insertions(+), 8 deletions(-) + +diff --git a/src/resolve/resolved-dns-query.c b/src/resolve/resolved-dns-query.c +index c5805111d21..8bc06079830 100644 +--- a/src/resolve/resolved-dns-query.c ++++ b/src/resolve/resolved-dns-query.c +@@ -433,6 +433,14 @@ int dns_query_new( + } else { + bool good = false; + ++ /* This (primarily) checks two things: ++ * ++ * 1. That the question is not empty ++ * 2. That all RR keys in the question objects are for the same domain ++ * ++ * Or in other words, a single DnsQuery object may be used to look up A+AAAA combination for ++ * the same domain name, or SRV+TXT (for DNS-SD services), but not for unrelated lookups. */ ++ + if (dns_question_size(question_utf8) > 0) { + r = dns_question_is_valid_for_query(question_utf8); + if (r < 0) +@@ -1032,6 +1040,8 @@ int dns_query_process_cname(DnsQuery *q) { + _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *cname = NULL; + DnsQuestion *question; + DnsResourceRecord *rr; ++ bool full_match = true; ++ DnsResourceKey *k; + int r; + + assert(q); +@@ -1041,13 +1051,44 @@ int dns_query_process_cname(DnsQuery *q) { + + question = dns_query_question_for_protocol(q, q->answer_protocol); + +- DNS_ANSWER_FOREACH(rr, q->answer) { +- r = dns_question_matches_rr(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); +- if (r < 0) +- return r; +- if (r > 0) +- return DNS_QUERY_MATCH; /* The answer matches directly, no need to follow cnames */ ++ /* Small reminder: our question will consist of one or more RR keys that match in name, but not in ++ * record type. Specifically, when we do an address lookup the question will typically consist of one ++ * A and one AAAA key lookup for the same domain name. When we get a response from a server we need ++ * to check if the answer answers all our questions to use it. Note that a response of CNAME/DNAME ++ * can answer both an A and the AAAA question for us, but an A/AAAA response only the relevant ++ * type. ++ * ++ * Hence we first check of the answers we collected are sufficient to answer all our questions ++ * directly. If one question wasn't answered we go on, waiting for more replies. However, if there's ++ * a CNAME/DNAME response we use it, and redirect to it, regardless if it was a response to the A or ++ * the AAAA query.*/ ++ ++ DNS_QUESTION_FOREACH(k, question) { ++ bool match = false; ++ ++ DNS_ANSWER_FOREACH(rr, q->answer) { ++ r = dns_resource_key_match_rr(k, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); ++ if (r < 0) ++ return r; ++ if (r > 0) { ++ match = true; /* Yay, we found an RR that matches the key we are looking for */ ++ break; ++ } ++ } ++ ++ if (!match) { ++ /* Hmm. :-( there's no response for this key. This doesn't match. */ ++ full_match = false; ++ break; ++ } ++ } + ++ if (full_match) ++ return DNS_QUERY_MATCH; /* The answer can answer our question in full, no need to follow CNAMEs/DNAMEs */ ++ ++ /* Let's see if there is a CNAME/DNAME to match. This case is simpler: we accept the CNAME/DNAME that ++ * matches any of our questions. */ ++ DNS_ANSWER_FOREACH(rr, q->answer) { + r = dns_question_matches_cname_or_dname(question, rr, DNS_SEARCH_DOMAIN_NAME(q->answer_search_domain)); + if (r < 0) + return r; +@@ -1056,7 +1097,7 @@ int dns_query_process_cname(DnsQuery *q) { + } + + if (!cname) +- return DNS_QUERY_NOMATCH; /* No match and no cname to follow */ ++ return DNS_QUERY_NOMATCH; /* No match and no CNAME/DNAME to follow */ + + if (q->flags & SD_RESOLVED_NO_CNAME) + return -ELOOP; +diff --git a/src/resolve/resolved-dns-query.h b/src/resolve/resolved-dns-query.h +index 5d12171b0a1..5d96cc06f84 100644 +--- a/src/resolve/resolved-dns-query.h ++++ b/src/resolve/resolved-dns-query.h +@@ -45,7 +45,14 @@ struct DnsQuery { + * that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names + * (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference + * between these two fields is mostly relevant only for explicit *hostname* lookups as well as the +- * domain suffixes of service lookups. */ ++ * domain suffixes of service lookups. ++ * ++ * Note that questions may consist of multiple RR keys at once, but they must be for the same domain ++ * name. This is used for A+AAAA and TXT+SRV lookups: we'll allocate a single DnsQuery object for ++ * them instead of two separate ones. That allows us minor optimizations with response handling: ++ * CNAME/DNAMEs of the first reply we get can already be used to follow the CNAME/DNAME chain for ++ * both, and we can take benefit of server replies that oftentimes put A responses into AAAA queries ++ * and vice versa (in the additional section). */ + DnsQuestion *question_idna; + DnsQuestion *question_utf8; + diff --git a/19080.patch b/19080.patch new file mode 100644 index 0000000..c8e1db4 --- /dev/null +++ b/19080.patch @@ -0,0 +1,67 @@ +From fce5b2ac2a51b9ecbfb258ff7e62f4e67a38d4c8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Fri, 12 Mar 2021 10:20:38 +0100 +Subject: [PATCH] sd-event: disable epoll_pwait2 for now + +This reverts the gist of commit 798445ab84cff51bde7fcf936f0fb19c37cf858c. + +Unfortunately the new syscall causes test-event to hang. 32 bit architectures +seem affected: i686 and arm32 in fedora koji. 32 bit build of test-event hangs +reliably under valgrind: + +$ PKG_CONFIG_LIBDIR=/usr/lib/pkgconfig meson build-32 -Dc_args=-m32 -Dc_link_args=-m32 -Dcpp_args=-m32 -Dcpp_link_args=-m32 && ninja -C build-32 test-event && valgrind build/test-event + +If I set epoll_pwait2_absent=true, so the new function is never called, then +the issue does not reproduce. It seems to be strictly tied to the syscall. + +On amd64, the syscall is not used, at least with the kernel that Fedora +provides. The kernel patch 58169a52ebc9a733aeb5bea857bc5daa71a301bb says: + + For timespec, only support this new interface on 2038 aware platforms + that define __kernel_timespec_t. So no CONFIG_COMPAT_32BIT_TIME. + +And Fedora sets CONFIG_COMPAT_32BIT_TIME=y. I expect most other distros will too. + +On amd64: epoll_wait_usec: epoll_pwait2: ret=-1 / errno=38 +On i686 (same kernel): epoll_wait_usec: epoll_pwait2: ret=2 / errno=0 + +Is this some kind of emulation? Anyway, it seems that this is what is going wrong. + +So let's disable the syscall until it becomes more widely available and the +kinks have been ironed out. + +Fixes test-event issue in #19052. +--- + src/libsystemd/sd-event/sd-event.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index 8f74b141015..b76b0623fe3 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -3808,10 +3808,15 @@ static int epoll_wait_usec( + int maxevents, + usec_t timeout) { + +- static bool epoll_pwait2_absent = false; + int r, msec; ++#if 0 ++ static bool epoll_pwait2_absent = false; + +- /* A wrapper that uses epoll_pwait2() if available, and falls back to epoll_wait() if not */ ++ /* A wrapper that uses epoll_pwait2() if available, and falls back to epoll_wait() if not. ++ * ++ * FIXME: this is temporarily disabled until epoll_pwait2() becomes more widely available. ++ * See https://github.com/systemd/systemd/pull/18973 and ++ * https://github.com/systemd/systemd/issues/19052. */ + + if (!epoll_pwait2_absent && timeout != USEC_INFINITY) { + struct timespec ts; +@@ -3829,6 +3834,7 @@ static int epoll_wait_usec( + + epoll_pwait2_absent = true; + } ++#endif + + if (timeout == USEC_INFINITY) + msec = -1; diff --git a/5cdb3f70ebe035323f4f079028a262669a2bbbf6.patch b/5cdb3f70ebe035323f4f079028a262669a2bbbf6.patch new file mode 100644 index 0000000..9e737ea --- /dev/null +++ b/5cdb3f70ebe035323f4f079028a262669a2bbbf6.patch @@ -0,0 +1,55 @@ +From 5cdb3f70ebe035323f4f079028a262669a2bbbf6 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Fri, 19 Mar 2021 06:26:53 +0900 +Subject: [PATCH] udev: do not try to assign invalid ifname + +Fixes #19038. +--- + src/udev/net/link-config.c | 18 +++++++----------- + 1 file changed, 7 insertions(+), 11 deletions(-) + +diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c +index f06ecd455df..31e5d0cd673 100644 +--- a/src/udev/net/link-config.c ++++ b/src/udev/net/link-config.c +@@ -441,8 +441,6 @@ static int link_config_apply_rtnl_settings(sd_netlink **rtnl, const link_config + + static int link_config_generate_new_name(const link_config_ctx *ctx, const link_config *config, sd_device *device, const char **ret_name) { + unsigned name_type = NET_NAME_UNKNOWN; +- const char *new_name = NULL; +- NamePolicy policy; + int r; + + assert(ctx); +@@ -460,7 +458,8 @@ static int link_config_generate_new_name(const link_config_ctx *ctx, const link_ + + if (ctx->enable_name_policy && config->name_policy) + for (NamePolicy *p = config->name_policy; *p != _NAMEPOLICY_INVALID; p++) { +- policy = *p; ++ const char *new_name = NULL; ++ NamePolicy policy = *p; + + switch (policy) { + case NAMEPOLICY_KERNEL: +@@ -496,16 +495,13 @@ static int link_config_generate_new_name(const link_config_ctx *ctx, const link_ + default: + assert_not_reached("invalid policy"); + } +- if (ifname_valid(new_name)) +- break; ++ if (ifname_valid(new_name)) { ++ log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name); ++ *ret_name = new_name; ++ return 0; ++ } + } + +- if (new_name) { +- log_device_debug(device, "Policy *%s* yields \"%s\".", name_policy_to_string(policy), new_name); +- *ret_name = new_name; +- return 0; +- } +- + if (config->name) { + log_device_debug(device, "Policies didn't yield a name, using specified Name=%s.", config->name); + *ret_name = config->name; diff --git a/f9b3afae96c72564cd4cd766555845f17e3c12a9.patch b/f9b3afae96c72564cd4cd766555845f17e3c12a9.patch new file mode 100644 index 0000000..9bbab91 --- /dev/null +++ b/f9b3afae96c72564cd4cd766555845f17e3c12a9.patch @@ -0,0 +1,85 @@ +From f9b3afae96c72564cd4cd766555845f17e3c12a9 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 19 Mar 2021 10:36:48 +0100 +Subject: [PATCH] repart: make sure to grow partition table after growing + backing loopback file + +This fixes the --size= switch, i.e. where we grow a disk image: after +growing it we need to expand the partition table so that its idea of the +the medium size matches the new reality. Otherwise our disk size +calculations in the subsequent steps might still use the original +ungrown size. + +(This used to work, I guess this was borked when libfdisk learnt the +concept of "minimized" partition tables) +--- + src/partition/repart.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/src/partition/repart.c b/src/partition/repart.c +index be16f5a067b..7b6201efa83 100644 +--- a/src/partition/repart.c ++++ b/src/partition/repart.c +@@ -3977,6 +3977,40 @@ static int find_root(char **ret, int *ret_fd) { + return log_error_errno(SYNTHETIC_ERRNO(ENODEV), "Failed to discover root block device."); + } + ++static int resize_pt(int fd) { ++ char procfs_path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; ++ _cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL; ++ int r; ++ ++ /* After resizing the backing file we need to resize the partition table itself too, so that it takes ++ * possession of the enlarged backing file. For this it suffices to open the device with libfdisk and ++ * immediately write it again, with no changes. */ ++ ++ c = fdisk_new_context(); ++ if (!c) ++ return log_oom(); ++ ++ xsprintf(procfs_path, "/proc/self/fd/%i", fd); ++ r = fdisk_assign_device(c, procfs_path, 0); ++ if (r < 0) ++ return log_error_errno(r, "Failed to open device '%s': %m", procfs_path); ++ ++ r = fdisk_has_label(c); ++ if (r < 0) ++ return log_error_errno(r, "Failed to determine whether disk '%s' has a disk label: %m", procfs_path); ++ if (r == 0) { ++ log_debug("Not resizing partition table, as there currently is none."); ++ return 0; ++ } ++ ++ r = fdisk_write_disklabel(c); ++ if (r < 0) ++ return log_error_errno(r, "Failed to write resized partition table: %m"); ++ ++ log_info("Resized partition table."); ++ return 1; ++} ++ + static int resize_backing_fd(const char *node, int *fd) { + char buf1[FORMAT_BYTES_MAX], buf2[FORMAT_BYTES_MAX]; + _cleanup_close_ int writable_fd = -1; +@@ -4029,6 +4063,10 @@ static int resize_backing_fd(const char *node, int *fd) { + /* Fallback to truncation, if fallocate() is not supported. */ + log_debug("Backing file system does not support fallocate(), falling back to ftruncate()."); + } else { ++ r = resize_pt(writable_fd); ++ if (r < 0) ++ return r; ++ + if (st.st_size == 0) /* Likely regular file just created by us */ + log_info("Allocated %s for '%s'.", buf2, node); + else +@@ -4042,6 +4080,10 @@ static int resize_backing_fd(const char *node, int *fd) { + return log_error_errno(errno, "Failed to grow '%s' from %s to %s by truncation: %m", + node, buf1, buf2); + ++ r = resize_pt(writable_fd); ++ if (r < 0) ++ return r; ++ + if (st.st_size == 0) /* Likely regular file just created by us */ + log_info("Sized '%s' to %s.", node, buf2); + else diff --git a/systemd.spec b/systemd.spec index 7eec651..052e16d 100644 --- a/systemd.spec +++ b/systemd.spec @@ -21,7 +21,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 248~rc4 -Release: 2%{?dist} +Release: 3%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -74,6 +74,20 @@ GIT_DIR=../../src/systemd/.git git diffab -M v233..master@{2017-06-15} -- hwdb/[ %endif # Backports of patches from upstream (0000–0499) +# +# Any patches which are "in preparation" upstream should be listed +# here, rather than in the next section. Packit CI will drop any +# patches in this range before applying upstream pull requests. + +# https://bugzilla.redhat.com/show_bug.cgi?id=1941335 +Patch0001: https://github.com/systemd/systemd/pull/19075.patch + +Patch0002: https://github.com/systemd/systemd/pull/19079.patch +Patch0003: https://github.com/systemd/systemd/pull/19080.patch + +Patch0004: https://github.com/systemd/systemd/commit/5cdb3f70ebe035323f4f079028a262669a2bbbf6.patch +Patch0005: https://github.com/systemd/systemd/commit/f9b3afae96c72564cd4cd766555845f17e3c12a9.patch +Patch0006: https://github.com/systemd/systemd/commit/0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d.patch # Downstream-only patches (5000–9999) # https://bugzilla.redhat.com/show_bug.cgi?id=1738828 @@ -82,9 +96,6 @@ Patch0500: use-bfq-scheduler.patch # https://github.com/systemd/systemd/pull/17050 Patch0501: https://github.com/systemd/systemd/pull/17050/commits/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch -# https://github.com/systemd/systemd/pull/18973 -Patch0502: 0001-sd-event-do-not-use-epoll_pwait2-tentatively.patch - %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 %endif @@ -955,11 +966,23 @@ getent passwd systemd-network &>/dev/null || useradd -r -u 192 -l -g systemd-net %files standalone-sysusers -f .file-list-standalone-sysusers %changelog +* Mon Mar 22 2021 Zbigniew Jędrzejewski-Szmek - 248~rc4-3 +- Fix hang when processing timers during DST switch in Europe/Dublin timezone (#1941335) +- Fix returning combined IPv4/IPv6 responses from systemd-resolved cache (#1940715) + (But note that the disablement of caching added previously is + retained until we can do more testing.) +- Minor fix to interface naming by udev +- Fix for systemd-repart --size + * Fri Mar 19 2021 Adam Williamson - 248~rc4-2 - Disable resolved cache via config snippet (#1940715) * Thu Mar 18 2021 Yu Watanabe - 248~rc4-1 -- Latest upstream prelease. +- Latest upstream prelease, see + https://github.com/systemd/systemd/blob/v248-rc4/NEWS. +- A bunch of documentation updates, correctness fixes, and systemd-networkd + features. +- Resolves #1933137, #1935084, #1933873, #1931181, #1933335, #1935062, #1927148. * Tue Mar 16 2021 Adam Williamson - 248~rc2-8 - Drop the resolved cache disablement config snippet