Version 248

This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-03-31 09:55:50 +02:00
parent a62a7c17cc
commit f0032c4da6
9 changed files with 10 additions and 905 deletions

View File

@ -1,55 +0,0 @@
From 9ac47d37a59142a66ac13f58bef197117ff53141 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
Date: Wed, 24 Mar 2021 11:42:39 +0100
Subject: [PATCH] Revert "resolved: gracefully handle with packets with too
large RR count"
This reverts commit 18674159ebbf622a9e6e5a45cc36b38f74dae315.
There are multiple reports that this breaks lookups for people, and reverting
this commit, even on the main branch (approx. v248-rc4), fixes the issue.
https://github.com/systemd/systemd/issues/18917#issuecomment-799421587
https://bodhi.fedoraproject.org/updates/FEDORA-2021-1c1a870ceb
---
src/resolve/resolved-dns-packet.c | 16 +---------------
1 file changed, 1 insertion(+), 15 deletions(-)
diff --git a/src/resolve/resolved-dns-packet.c b/src/resolve/resolved-dns-packet.c
index abc978ab83..15c8123f6a 100644
--- a/src/resolve/resolved-dns-packet.c
+++ b/src/resolve/resolved-dns-packet.c
@@ -2271,18 +2271,6 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
bool cache_flush = false;
size_t start;
- if (p->rindex == p->size) {
- /* If we reached the end of the packet already, but there are still more RRs
- * declared, then that's a corrupt packet. Let's accept the packet anyway, since it's
- * apparently a common bug in routers. Let's however suppress OPT support in this
- * case, so that we force the rest of the logic into lowest DNS baseline support. Or
- * to say this differently: if the DNS server doesn't even get the RR counts right,
- * it's highly unlikely it gets EDNS right. */
- log_debug("More resource records declared in packet than included, suppressing OPT.");
- bad_opt = true;
- break;
- }
-
r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
if (r < 0)
return r;
@@ -2382,10 +2370,8 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
previous = dns_resource_record_ref(rr);
}
- if (bad_opt) {
+ if (bad_opt)
p->opt = dns_resource_record_unref(p->opt);
- p->opt_start = p->opt_size = SIZE_MAX;
- }
*ret_answer = TAKE_PTR(answer);
--
2.30.2

View File

@ -1,36 +0,0 @@
From 0e557eef37c9ebcc8f5c19fc6fc44b6fd617cc5d Mon Sep 17 00:00:00 2001
From: Sergey Bugaev <bugaevc@gmail.com>
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

View File

@ -1,415 +0,0 @@
From 169615c9a8cdc54d748d4dfc8279be9b3c2bec44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
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?= <zbyszek@in.waw.pl>
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?= <zbyszek@in.waw.pl>
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?= <zbyszek@in.waw.pl>
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?= <zbyszek@in.waw.pl>
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

View File

@ -1,178 +0,0 @@
From 4cba52cc7a2191d0b38e605801c60d8648bc67e2 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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 <lennart@poettering.net>
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;

View File

@ -1,67 +0,0 @@
From fce5b2ac2a51b9ecbfb258ff7e62f4e67a38d4c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
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;

View File

@ -1,55 +0,0 @@
From 5cdb3f70ebe035323f4f079028a262669a2bbbf6 Mon Sep 17 00:00:00 2001
From: Yu Watanabe <watanabe.yu+github@gmail.com>
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;

View File

@ -1,85 +0,0 @@
From f9b3afae96c72564cd4cd766555845f17e3c12a9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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

View File

@ -1 +1 @@
SHA512 (systemd-248-rc4.tar.gz) = 022e8aabdc84c45ea06928c7b373c13f99d78fd808d9c07d3cd79dae5a2356f70d012eafbc749a588ddfcc2b1d0155f65f33ee240c4f15190d16f784803ffeac SHA512 (systemd-248.tar.gz) = 486f6ac6c2897a2aac97a59306091a03fd50768340407401e1f088ea5b21c67dae726bff4cbe53cec6b89a8f0ee72205b340165a4fe3a3c16cff6d176506c6e0

View File

@ -20,8 +20,8 @@
Name: systemd Name: systemd
Url: https://www.freedesktop.org/wiki/Software/systemd Url: https://www.freedesktop.org/wiki/Software/systemd
Version: 248~rc4 Version: 248
Release: 6%{?dist} Release: 1%{?dist}
# For a breakdown of the licensing, see README # For a breakdown of the licensing, see README
License: LGPLv2+ and MIT and GPLv2+ License: LGPLv2+ and MIT and GPLv2+
Summary: System and Service Manager Summary: System and Service Manager
@ -79,17 +79,6 @@ GIT_DIR=../../src/systemd/.git git diffab -M v233..master@{2017-06-15} -- hwdb/[
# here, rather than in the next section. Packit CI will drop any # here, rather than in the next section. Packit CI will drop any
# patches in this range before applying upstream pull requests. # 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
Patch0007: 0001-Revert-resolved-gracefully-handle-with-packets-with-.patch
# Downstream-only patches (50009999) # Downstream-only patches (50009999)
# https://bugzilla.redhat.com/show_bug.cgi?id=1738828 # https://bugzilla.redhat.com/show_bug.cgi?id=1738828
@ -987,6 +976,13 @@ fi
%files standalone-sysusers -f .file-list-standalone-sysusers %files standalone-sysusers -f .file-list-standalone-sysusers
%changelog %changelog
* Wed Mar 31 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 248-1
- Latest upstream release, see
https://github.com/systemd/systemd/blob/v248/NEWS.
- The changes since -rc4 are rather small, various fixes all over the place.
A fix to how systemd-oomd selects a candidate to kill, and more debug logging
to make this more transparent.
* Tue Mar 30 2021 Anita Zhang <the.anitazha@gmail.com> - 248~rc4-6 * Tue Mar 30 2021 Anita Zhang <the.anitazha@gmail.com> - 248~rc4-6
- Increase oomd user memory pressure limit to 50% (#1941170) - Increase oomd user memory pressure limit to 50% (#1941170)