From 4b8c80a811af8258c136f5e7000fc0cd0adf8dc5 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Feb 24 2020 11:32:31 +0000 Subject: import systemd-239-18.el8_1.4 --- diff --git a/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch b/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch new file mode 100644 index 0000000..117dca9 --- /dev/null +++ b/SOURCES/0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch @@ -0,0 +1,136 @@ +From c4a7251ed4ca98d6d4faf6228ffe68166c1906cb Mon Sep 17 00:00:00 2001 +From: HATAYAMA Daisuke +Date: Mon, 28 Oct 2019 19:35:24 +0900 +Subject: [PATCH] core, job: fix breakage of ordering dependencies by systemctl + reload command + +Currently, systemctl reload command breaks ordering dependencies if it's +executed when its target service unit is in activating state. + +For example, prepare A.service, B.service and C.target as follows: + + # systemctl cat A.service B.service C.target + # /etc/systemd/system/A.service + [Unit] + Description=A + + [Service] + Type=oneshot + ExecStart=/usr/bin/echo A1 + ExecStart=/usr/bin/sleep 60 + ExecStart=/usr/bin/echo A2 + ExecReload=/usr/bin/echo A reloaded + RemainAfterExit=yes + + # /etc/systemd/system/B.service + [Unit] + Description=B + After=A.service + + [Service] + Type=oneshot + ExecStart=/usr/bin/echo B + RemainAfterExit=yes + + # /etc/systemd/system/C.target + [Unit] + Description=C + Wants=A.service B.service + +Start them. + + # systemctl daemon-reload + # systemctl start C.target + +Then, we have: + + # LANG=C journalctl --no-pager -u A.service -u B.service -u C.target -b + -- Logs begin at Mon 2019-09-09 00:25:06 EDT, end at Thu 2019-10-24 22:28:47 EDT. -- + Oct 24 22:27:47 localhost.localdomain systemd[1]: Starting A... + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Child 967 belongs to A.service. + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/sleep 60 + Oct 24 22:27:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/sleep as 968 + Oct 24 22:27:47 localhost.localdomain systemd[968]: A.service: Executing: /usr/bin/sleep 60 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Trying to enqueue job A.service/reload/replace + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Merged into running job, re-running: A.service/reload as 1288 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Enqueued job A.service/reload as 1288 + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Unit cannot be reloaded because it is inactive. + Oct 24 22:27:52 localhost.localdomain systemd[1]: A.service: Job 1288 A.service/reload finished, result=invalid + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Passing 0 fds to service + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: About to execute: /usr/bin/echo B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Forked /usr/bin/echo as 970 + Oct 24 22:27:52 localhost.localdomain systemd[970]: B.service: Executing: /usr/bin/echo B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Failed to send unit change signal for B.service: Connection reset by peer + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed dead -> start + Oct 24 22:27:52 localhost.localdomain systemd[1]: Starting B... + Oct 24 22:27:52 localhost.localdomain echo[970]: B + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Child 970 belongs to B.service. + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Changed start -> exited + Oct 24 22:27:52 localhost.localdomain systemd[1]: B.service: Job 1371 B.service/start finished, result=done + Oct 24 22:27:52 localhost.localdomain systemd[1]: Started B. + Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Job 1287 C.target/start finished, result=done + Oct 24 22:27:52 localhost.localdomain systemd[1]: Reached target C. + Oct 24 22:27:52 localhost.localdomain systemd[1]: C.target: Failed to send unit change signal for C.target: Connection reset by peer + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 968 belongs to A.service. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Running next main command for state start. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Passing 0 fds to service + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: About to execute: /usr/bin/echo A2 + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Forked /usr/bin/echo as 972 + Oct 24 22:28:47 localhost.localdomain systemd[972]: A.service: Executing: /usr/bin/echo A2 + Oct 24 22:28:47 localhost.localdomain echo[972]: A2 + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Child 972 belongs to A.service. + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Main process exited, code=exited, status=0/SUCCESS + Oct 24 22:28:47 localhost.localdomain systemd[1]: A.service: Changed start -> exited + +The issue occurs not only in reload command, i.e.: + + - reload + - try-restart + - reload-or-restart + - reload-or-try-restart commands + +The cause of this issue is that job_type_collapse() doesn't take care of the +activating state. + +Fixes: #10464 +(cherry picked from commit d1559793df555212271e490a4a72f55826caf5b4) +(cherry picked from commit cb084637ba1c8558f1538ce300c5520a6764dc76) +Resolves: #1781712 +--- + src/core/job.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 8552ffb704..769ed6d603 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -403,21 +403,21 @@ JobType job_type_collapse(JobType t, Unit *u) { + + case JOB_TRY_RESTART: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RESTART; + + case JOB_TRY_RELOAD: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_NOP; + + return JOB_RELOAD; + + case JOB_RELOAD_OR_START: + s = unit_active_state(u); +- if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ if (!UNIT_IS_ACTIVE_OR_RELOADING(s)) + return JOB_START; + + return JOB_RELOAD; diff --git a/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch b/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch new file mode 100644 index 0000000..d243bc1 --- /dev/null +++ b/SOURCES/0224-syslog-fix-segfault-in-syslog_parse_priority.patch @@ -0,0 +1,110 @@ +From a9e1b3a33f65721e7f77f8d8253512dd16cbafdb Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 8 Aug 2018 18:27:15 +0900 +Subject: [PATCH] syslog: fix segfault in syslog_parse_priority() + +(cherry picked from commit a5ee33b951cfa22db53d0274c9c6c0d9d4dae39d) +(cherry picked from commit 8bd791fb3a8e85063e297204bdef8004aacd22b1) +Related: #1781712 +--- + src/basic/syslog-util.c | 20 +++++++++++--------- + src/journal/test-journal-syslog.c | 20 ++++++++++++++++++++ + 2 files changed, 31 insertions(+), 9 deletions(-) + +diff --git a/src/basic/syslog-util.c b/src/basic/syslog-util.c +index 21461fa581..fe129482f3 100644 +--- a/src/basic/syslog-util.c ++++ b/src/basic/syslog-util.c +@@ -10,7 +10,8 @@ + + int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + int a = 0, b = 0, c = 0; +- int k; ++ const char *end; ++ size_t k; + + assert(p); + assert(*p); +@@ -19,21 +20,22 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + if ((*p)[0] != '<') + return 0; + +- if (!strchr(*p, '>')) ++ end = strchr(*p, '>'); ++ if (!end) + return 0; + +- if ((*p)[2] == '>') { ++ k = end - *p; ++ assert(k > 0); ++ ++ if (k == 2) + c = undecchar((*p)[1]); +- k = 3; +- } else if ((*p)[3] == '>') { ++ else if (k == 3) { + b = undecchar((*p)[1]); + c = undecchar((*p)[2]); +- k = 4; +- } else if ((*p)[4] == '>') { ++ } else if (k == 4) { + a = undecchar((*p)[1]); + b = undecchar((*p)[2]); + c = undecchar((*p)[3]); +- k = 5; + } else + return 0; + +@@ -46,7 +48,7 @@ int syslog_parse_priority(const char **p, int *priority, bool with_facility) { + else + *priority = (*priority & LOG_FACMASK) | c; + +- *p += k; ++ *p += k + 1; + return 1; + } + +diff --git a/src/journal/test-journal-syslog.c b/src/journal/test-journal-syslog.c +index 7294cde032..120477cc9f 100644 +--- a/src/journal/test-journal-syslog.c ++++ b/src/journal/test-journal-syslog.c +@@ -4,6 +4,7 @@ + #include "journald-syslog.h" + #include "macro.h" + #include "string-util.h" ++#include "syslog-util.h" + + static void test_syslog_parse_identifier(const char *str, + const char *ident, const char *pid, const char *rest, int ret) { +@@ -19,6 +20,17 @@ static void test_syslog_parse_identifier(const char *str, + assert_se(streq(buf, rest)); + } + ++static void test_syslog_parse_priority(const char *str, int priority, int ret) { ++ const char *buf = str; ++ int priority2, ret2; ++ ++ ret2 = syslog_parse_priority(&buf, &priority2, false); ++ ++ assert_se(ret == ret2); ++ if (ret2 == 1) ++ assert_se(priority == priority2); ++} ++ + int main(void) { + test_syslog_parse_identifier("pidu[111]: xxx", "pidu", "111", "xxx", 11); + test_syslog_parse_identifier("pidu: xxx", "pidu", NULL, "xxx", 6); +@@ -33,5 +45,13 @@ int main(void) { + test_syslog_parse_identifier("pidu: ", "pidu", NULL, "", 6); + test_syslog_parse_identifier("pidu : ", NULL, NULL, "pidu : ", 0); + ++ test_syslog_parse_priority("<>", 0, 0); ++ test_syslog_parse_priority("<>aaa", 0, 0); ++ test_syslog_parse_priority("", 0, 0); ++ test_syslog_parse_priority("aaa", 0, 0); ++ test_syslog_parse_priority(" ", 0, 0); ++ test_syslog_parse_priority(" aaa", 0, 0); ++ /* TODO: add test cases of valid priorities */ ++ + return 0; + } diff --git a/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch b/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch new file mode 100644 index 0000000..ff2e481 --- /dev/null +++ b/SOURCES/0225-journald-fixed-assertion-failure-when-system-journal.patch @@ -0,0 +1,28 @@ +From 7fdcc0e9cc7f047a778a2f1776d2398f46c6ac86 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Renaud=20M=C3=A9trich?= + <1163635+rmetrich@users.noreply.github.com> +Date: Mon, 3 Sep 2018 05:42:39 +0200 +Subject: [PATCH] journald: fixed assertion failure when system journal + rotation fails (#9893) + +(cherry picked from commit fd790d6f09b10a87b007b71403cb018f18ff91c9) +(cherry picked from commit 33aa231f5bf3335cdacfb38ffba757865019ce4d) +Related: #1781712 +--- + src/journal/journald-server.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 8de45552f6..f2d2856e03 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1041,7 +1041,8 @@ int server_flush_to_var(Server *s, bool require_flag_file) { + r = 0; + + finish: +- journal_file_post_change(s->system_journal); ++ if (s->system_journal) ++ journal_file_post_change(s->system_journal); + + s->runtime_journal = journal_file_close(s->runtime_journal); + diff --git a/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch b/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch new file mode 100644 index 0000000..57d7275 --- /dev/null +++ b/SOURCES/0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch @@ -0,0 +1,29 @@ +From 9896fd236594fba4c2288ab33884f23a709565ab Mon Sep 17 00:00:00 2001 +From: Frantisek Sumsal +Date: Fri, 15 Mar 2019 10:05:33 +0100 +Subject: [PATCH] test: use PBKDF2 instead of Argon2 in cryptsetup... + +to reduce memory requirements for volume manipulation. Also, +to further improve the test performance, reduce number of PBKDF +iterations to 1000 (allowed minimum). + +(cherry picked from commit 5b69d297c153478f6f5e74ba66e1f4e5b6422baf) +(cherry picked from commit a7f18f9ef4abc7e0732d1710ead2a18a38c3ec6d) +Related: #1781712 +--- + test/TEST-02-CRYPTSETUP/test.sh | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh +index 545602e17a..c38e56f72e 100755 +--- a/test/TEST-02-CRYPTSETUP/test.sh ++++ b/test/TEST-02-CRYPTSETUP/test.sh +@@ -29,7 +29,7 @@ check_result_qemu() { + test_setup() { + create_empty_image + echo -n test >$TESTDIR/keyfile +- cryptsetup -q luksFormat ${LOOPDEV}p2 $TESTDIR/keyfile ++ cryptsetup -q luksFormat --pbkdf pbkdf2 --pbkdf-force-iterations 1000 ${LOOPDEV}p2 $TESTDIR/keyfile + cryptsetup luksOpen ${LOOPDEV}p2 varcrypt <$TESTDIR/keyfile + mkfs.ext4 -L var /dev/mapper/varcrypt + mkdir -p $TESTDIR/root diff --git a/SOURCES/0227-test-mask-several-unnecessary-services.patch b/SOURCES/0227-test-mask-several-unnecessary-services.patch new file mode 100644 index 0000000..d1a4f13 --- /dev/null +++ b/SOURCES/0227-test-mask-several-unnecessary-services.patch @@ -0,0 +1,252 @@ +From 0b16c6baa6b24c984a1b4bcd7026172f1627fe92 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Thu, 1 Nov 2018 17:26:36 +0900 +Subject: [PATCH] test: mask several unnecessary services + +This may make CIs run faster. + +(cherry picked from commit 056ae88152a722bdbea54ff33db815d585c8b9c6) +(cherry picked from commit c748b95f5a00b6d9c46026c3d251c40437e6b64a) +Related: #1781712 +--- + test/TEST-02-CRYPTSETUP/test.sh | 8 ++++++++ + test/TEST-03-JOBS/test.sh | 8 ++++++++ + test/TEST-04-JOURNAL/test.sh | 8 ++++++++ + test/TEST-05-RLIMITS/test.sh | 8 ++++++++ + test/TEST-07-ISSUE-1981/test.sh | 8 ++++++++ + test/TEST-11-ISSUE-3166/test.sh | 8 ++++++++ + test/TEST-12-ISSUE-3171/test.sh | 8 ++++++++ + test/TEST-13-NSPAWN-SMOKE/test.sh | 8 ++++++++ + test/TEST-18-FAILUREACTION/test.sh | 7 +++++++ + test/TEST-19-DELEGATE/test.sh | 8 ++++++++ + test/TEST-20-MAINPIDGAMES/test.sh | 8 ++++++++ + test/TEST-23-TYPE-EXEC/test.sh | 8 ++++++++ + 12 files changed, 95 insertions(+) + +diff --git a/test/TEST-02-CRYPTSETUP/test.sh b/test/TEST-02-CRYPTSETUP/test.sh +index c38e56f72e..97eb2f409e 100755 +--- a/test/TEST-02-CRYPTSETUP/test.sh ++++ b/test/TEST-02-CRYPTSETUP/test.sh +@@ -45,6 +45,14 @@ test_setup() { + + setup_basic_environment + ++ # mask some services that we do not want to run in these tests ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-journal-catalog-update.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-networkd.socket ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-resolved.service ++ ln -fs /dev/null $initdir/etc/systemd/system/systemd-machined.service ++ + # setup the testsuite service + cat >$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system.conf <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service <$initdir/etc/systemd/system/testsuite.service < +Date: Mon, 21 Oct 2019 18:39:39 +0200 +Subject: [PATCH] test: bump the second partition's size to 50M + +The former size (10M) caused systemd-journald to crash with SIGABRT when +used on a LUKS2 partition, as the LUKS2 metadata consume a significant +part of the 10M partition, thus leaving no space for the journal file +itself (relevant for TEST-02-CRYPTSETUP). This change has been present +in upstream for a while anyway. + +rhel-only + +(cherry picked from commit 27d1acaa1d4c9299db461f0f1922c573be6a52c0) +Related: #1781712 +--- + test/test-functions | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/test-functions b/test/test-functions +index af9d16140f..fe25a501da 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -433,7 +433,7 @@ create_empty_image() { + [ -b "$LOOPDEV" ] || return 1 + echo "LOOPDEV=$LOOPDEV" >> $STATEFILE + sfdisk "$LOOPDEV" < +Date: Thu, 17 Jan 2019 18:13:03 +0100 +Subject: [PATCH] sd-bus: make rqueue/wqueue sizes of type size_t + +Let's do this like we usually do and size arrays with size_t. + +We already do this for the "allocated" counter correctly, and externally +we expose the queue sizes as uint64_t anyway, hence there's really no +point in usigned "unsigned" internally. + +(cherry picked from commit 143d4e045a798ccc87889b2a8a60d7fbe44be441) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-internal.h | 4 ++-- + src/libsystemd/sd-bus/sd-bus.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 90e6028983..2d21319df5 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -221,11 +221,11 @@ struct sd_bus { + size_t rbuffer_size; + + sd_bus_message **rqueue; +- unsigned rqueue_size; ++ size_t rqueue_size; + size_t rqueue_allocated; + + sd_bus_message **wqueue; +- unsigned wqueue_size; ++ size_t wqueue_size; + size_t windex; + size_t wqueue_allocated; + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 1c9e967ae0..64026f7ee1 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2080,7 +2080,7 @@ _public_ int sd_bus_call( + _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = sd_bus_message_ref(_m); + usec_t timeout; + uint64_t cookie; +- unsigned i; ++ size_t i; + int r; + + bus_assert_return(m, -EINVAL, error); diff --git a/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch b/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch new file mode 100644 index 0000000..0074f56 --- /dev/null +++ b/SOURCES/0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch @@ -0,0 +1,51 @@ +From 90dedb47d2cb060a366d12bf467f03fa20c5ed24 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:14:17 +0100 +Subject: [PATCH] sd-bus: reorder bus ref and bus message ref handling + +Let's always place handling of these references together, so that all +reference counting during allocation is at a single place. + +(cherry picked from commit e593b6a87a335267e5f7238b14683b7f840a01a3) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 53cbd675b7..2ea3c5bba9 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -461,7 +461,6 @@ int bus_message_from_header( + if (!m) + return -ENOMEM; + +- m->n_ref = 1; + m->sealed = true; + m->header = header; + m->header_accessible = header_accessible; +@@ -515,7 +514,9 @@ int bus_message_from_header( + m->creds.mask |= SD_BUS_CREDS_SELINUX_CONTEXT; + } + ++ m->n_ref = 1; + m->bus = sd_bus_ref(bus); ++ + *ret = TAKE_PTR(m); + + return 0; +@@ -588,13 +589,13 @@ _public_ int sd_bus_message_new( + return -ENOMEM; + + t->n_ref = 1; ++ t->bus = sd_bus_ref(bus); + t->header = (struct bus_header*) ((uint8_t*) t + ALIGN(sizeof(struct sd_bus_message))); + t->header->endian = BUS_NATIVE_ENDIAN; + t->header->type = type; + t->header->version = bus->message_version; + t->allow_fds = bus->can_fds || !IN_SET(bus->state, BUS_HELLO, BUS_RUNNING); + t->root_container.need_offsets = BUS_MESSAGE_IS_GVARIANT(t); +- t->bus = sd_bus_ref(bus); + + if (bus->allow_interactive_authorization) + t->header->flags |= BUS_MESSAGE_ALLOW_INTERACTIVE_AUTHORIZATION; diff --git a/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch b/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch new file mode 100644 index 0000000..fbd6a7f --- /dev/null +++ b/SOURCES/0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch @@ -0,0 +1,32 @@ +From d2725078f0da567eb2bcae3bef53f013d7fa3ba5 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:15:37 +0100 +Subject: [PATCH] sd-bus: make sure dispatch_rqueue() initializes return + parameter on all types of success + +Let's make sure our own code follows coding style and initializes all +return values on all types of success (and leaves it uninitialized in +all types of failure). + +(cherry picked from commit c0bc4ec5cc17ac61773d1e9362b0ffa8382c1ff1) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 64026f7ee1..55b008cc9f 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -1814,8 +1814,10 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd + r = bus_read_message(bus, hint_priority, priority); + if (r < 0) + return r; +- if (r == 0) ++ if (r == 0) { ++ *m = NULL; + return ret; ++ } + + ret = 1; + } diff --git a/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch b/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch new file mode 100644 index 0000000..335c018 --- /dev/null +++ b/SOURCES/0232-sd-bus-drop-two-inappropriate-empty-lines.patch @@ -0,0 +1,31 @@ +From e81231e9a88ebc68c715010ce288c1d59c52e88f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:18:18 +0100 +Subject: [PATCH] sd-bus: drop two inappropriate empty lines + +(cherry picked from commit 39feb2ce417e54cf9746e64b5dfd610cef6ac440) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 55b008cc9f..01060d105c 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -2634,7 +2634,6 @@ static int process_builtin(sd_bus *bus, sd_bus_message *m) { + SD_BUS_ERROR_UNKNOWN_METHOD, + "Unknown method '%s' on interface '%s'.", m->member, m->interface); + } +- + if (r < 0) + return r; + +@@ -2758,7 +2757,6 @@ static int process_running(sd_bus *bus, bool hint_priority, int64_t priority, sd + return r; + + *ret = TAKE_PTR(m); +- + return 1; + } + diff --git a/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch b/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch new file mode 100644 index 0000000..03ea861 --- /dev/null +++ b/SOURCES/0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch @@ -0,0 +1,33 @@ +From fb04f17617458d2d3d09e0bef29f1255d4d3500c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 21:06:30 +0100 +Subject: [PATCH] sd-bus: initialize mutex after we allocated the wqueue + +That way the mutex doesn't have to be destroyed when we exit early due +to OOM. + +(cherry picked from commit 2fe9a10d7695c4c3a748969a0d1662c624e50e5e) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/sd-bus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 01060d105c..e49d58137d 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -248,12 +248,12 @@ _public_ int sd_bus_new(sd_bus **ret) { + b->original_pid = getpid_cached(); + b->n_groups = (size_t) -1; + +- assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); +- + /* We guarantee that wqueue always has space for at least one entry */ + if (!GREEDY_REALLOC(b->wqueue, b->wqueue_allocated, 1)) + return -ENOMEM; + ++ assert_se(pthread_mutex_init(&b->memfd_cache_mutex, NULL) == 0); ++ + *ret = TAKE_PTR(b); + return 0; + } diff --git a/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch b/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch new file mode 100644 index 0000000..732ad35 --- /dev/null +++ b/SOURCES/0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch @@ -0,0 +1,74 @@ +From 51c839c733ff53061807d92326830b5fe8499041 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 21:07:42 +0100 +Subject: [PATCH] sd-bus: always go through sd_bus_unref() to free messages + +Don't try to be smart, don't bypass the ref counting logic if there's no +real reason to. + +This matters if we want to tweak the ref counting logic later. + +(cherry picked from commit b41812d1e308de03c879cfca490105216d528c4b) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index 2ea3c5bba9..ac19cc04bf 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -138,8 +138,6 @@ static sd_bus_message* message_free(sd_bus_message *m) { + return mfree(m); + } + +-DEFINE_TRIVIAL_CLEANUP_FUNC(sd_bus_message*, message_free); +- + static void *message_extend_fields(sd_bus_message *m, size_t align, size_t sz, bool add_offset) { + void *op, *np; + size_t old_size, new_size, start; +@@ -531,7 +529,7 @@ int bus_message_from_malloc( + const char *label, + sd_bus_message **ret) { + +- _cleanup_(message_freep) sd_bus_message *m = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL; + size_t sz; + int r; + +@@ -651,7 +649,7 @@ _public_ int sd_bus_message_new_method_call( + const char *interface, + const char *member) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(bus, -ENOTCONN); +@@ -696,7 +694,7 @@ static int message_new_reply( + uint8_t type, + sd_bus_message **m) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + uint64_t cookie; + int r; + +@@ -747,7 +745,7 @@ _public_ int sd_bus_message_new_method_error( + sd_bus_message **m, + const sd_bus_error *e) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert_return(sd_bus_error_is_set(e), -EINVAL); +@@ -850,7 +848,7 @@ int bus_message_new_synthetic_error( + const sd_bus_error *e, + sd_bus_message **m) { + +- _cleanup_(message_freep) sd_bus_message *t = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *t = NULL; + int r; + + assert(bus); diff --git a/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch b/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch new file mode 100644 index 0000000..cf6db16 --- /dev/null +++ b/SOURCES/0235-bus-message-introduce-two-kinds-of-references-to-bus.patch @@ -0,0 +1,182 @@ +From 02d55f8f5bfd38ed2958c7e55707cadb058071be Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:18:54 +0100 +Subject: [PATCH] bus-message: introduce two kinds of references to bus + messages + +Before this commit bus messages had a single reference count: when it +reached zero the message would be freed. This simple approach meant a +cyclic dependency was typically seen: a message that was enqueued in a +bus connection object would reference the bus connection object but also +itself be referenced by the bus connection object. So far out strategy +to avoid cases like this was: make sure to process the bus connection +regularly so that messages don#t stay queued, and at exit flush/close +the connection so that the message queued would be emptied, and thus the +cyclic dependencies resolved. Im many cases this isn't done properly +however. + +With this change, let's address the issue more systematically: let's +break the reference cycle. Specifically, there are now two types of +references to a bus message: + +1. A regular one, which keeps both the message and the bus object it is + associated with pinned. + +2. A "queue" reference, which is weaker: it pins the message, but not + the bus object it is associated with. + +The idea is then that regular user handling uses regular references, but +when a message is enqueued on its connection, then this takes a "queue" +reference instead. This then means that a queued message doesn't imply +the connection itself remains pinned, only regular references to the +connection or a message associated with it do. Thus, if we end up in the +situation where a user allocates a bus and a message and enqueues the +latter in the former and drops all refs to both, then this will detect +this case and free both. + +Note that this scheme isn't perfect, it only covers references between +messages and the busses they are associated with. If OTOH a bus message +is enqueued on a different bus than it is associated with cyclic deps +cannot be recognized with this simple algorithm, and thus if you enqueue +a message associated with a bus A on a bus B, and another message +associated with bus B on a bus A, a cyclic ref will be in effect and not +be discovered. However, given that this is an exotic case (though one +that happens, consider systemd-bus-stdio-bridge), it should be OK not to +cover with this, and people have to explicit flush all queues on exit in +that case. + +Note that this commit only establishes the separate reference counters +per message. A follow-up commit will start making use of this from the +bus connection object. + +(cherry picked from commit 1b3f9dd759ca0ea215e7b89f8ce66d1b724497b9) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-message.c | 60 ++++++++++++++++++++++++++--- + src/libsystemd/sd-bus/bus-message.h | 14 ++++++- + 2 files changed, 68 insertions(+), 6 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-message.c b/src/libsystemd/sd-bus/bus-message.c +index ac19cc04bf..ce7e67ecf2 100644 +--- a/src/libsystemd/sd-bus/bus-message.c ++++ b/src/libsystemd/sd-bus/bus-message.c +@@ -120,7 +120,8 @@ static sd_bus_message* message_free(sd_bus_message *m) { + + message_reset_parts(m); + +- sd_bus_unref(m->bus); ++ /* Note that we don't unref m->bus here. That's already done by sd_bus_message_unref() as each user ++ * reference to the bus message also is considered a reference to the bus connection itself. */ + + if (m->free_fds) { + close_many(m->fds, m->n_fds); +@@ -893,27 +894,76 @@ int bus_message_new_synthetic_error( + } + + _public_ sd_bus_message* sd_bus_message_ref(sd_bus_message *m) { +- + if (!m) + return NULL; + +- assert(m->n_ref > 0); ++ /* We are fine if this message so far was either explicitly reffed or not reffed but queued into at ++ * least one bus connection object. */ ++ assert(m->n_ref > 0 || m->n_queued > 0); ++ + m->n_ref++; + ++ /* Each user reference to a bus message shall also be considered a ref on the bus */ ++ sd_bus_ref(m->bus); + return m; + } + + _public_ sd_bus_message* sd_bus_message_unref(sd_bus_message *m) { +- + if (!m) + return NULL; + + assert(m->n_ref > 0); ++ ++ sd_bus_unref(m->bus); /* Each regular ref is also a ref on the bus connection. Let's hence drop it ++ * here. Note we have to do this before decrementing our own n_ref here, since ++ * otherwise, if this message is currently queued sd_bus_unref() might call ++ * bus_message_unref_queued() for this which might then destroy the message ++ * while we are still processing it. */ + m->n_ref--; + +- if (m->n_ref > 0) ++ if (m->n_ref > 0 || m->n_queued > 0) + return NULL; + ++ /* Unset the bus field if neither the user has a reference nor this message is queued. We are careful ++ * to reset the field only after the last reference to the bus is dropped, after all we might keep ++ * multiple references to the bus, once for each reference kept on outselves. */ ++ m->bus = NULL; ++ ++ return message_free(m); ++} ++ ++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus) { ++ if (!m) ++ return NULL; ++ ++ /* If this is a different bus than the message is associated with, then implicitly turn this into a ++ * regular reference. This means that you can create a memory leak by enqueuing a message generated ++ * on one bus onto another at the same time as enqueueing a message from the second one on the first, ++ * as we'll not detect the cyclic references there. */ ++ if (bus != m->bus) ++ return sd_bus_message_ref(m); ++ ++ assert(m->n_ref > 0 || m->n_queued > 0); ++ m->n_queued++; ++ ++ return m; ++} ++ ++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus) { ++ if (!m) ++ return NULL; ++ ++ if (bus != m->bus) ++ return sd_bus_message_unref(m); ++ ++ assert(m->n_queued > 0); ++ m->n_queued--; ++ ++ if (m->n_ref > 0 || m->n_queued > 0) ++ return NULL; ++ ++ m->bus = NULL; ++ + return message_free(m); + } + +diff --git a/src/libsystemd/sd-bus/bus-message.h b/src/libsystemd/sd-bus/bus-message.h +index 97f6060e30..ded88005e2 100644 +--- a/src/libsystemd/sd-bus/bus-message.h ++++ b/src/libsystemd/sd-bus/bus-message.h +@@ -51,7 +51,16 @@ struct bus_body_part { + }; + + struct sd_bus_message { +- unsigned n_ref; ++ /* Caveat: a message can be referenced in two different ways: the main (user-facing) way will also ++ * pin the bus connection object the message is associated with. The secondary way ("queued") is used ++ * when a message is in the read or write queues of the bus connection object, which will not pin the ++ * bus connection object. This is necessary so that we don't have to have a pair of cyclic references ++ * between a message that is queued and its connection: as soon as a message is only referenced by ++ * the connection (by means of being queued) and the connection itself has no other references it ++ * will be freed. */ ++ ++ unsigned n_ref; /* Counter of references that pin the connection */ ++ unsigned n_queued; /* Counter of references that do not pin the connection */ + + sd_bus *bus; + +@@ -216,3 +225,6 @@ int bus_message_append_sender(sd_bus_message *m, const char *sender); + + void bus_message_set_sender_driver(sd_bus *bus, sd_bus_message *m); + void bus_message_set_sender_local(sd_bus *bus, sd_bus_message *m); ++ ++sd_bus_message* bus_message_ref_queued(sd_bus_message *m, sd_bus *bus); ++sd_bus_message* bus_message_unref_queued(sd_bus_message *m, sd_bus *bus); diff --git a/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch b/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch new file mode 100644 index 0000000..2ce2ef3 --- /dev/null +++ b/SOURCES/0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch @@ -0,0 +1,74 @@ +From f16b5124274f35c475cb70fa936567877a4b74f9 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 31 Jan 2020 11:34:45 +0100 +Subject: [PATCH] sd-bus: introduce API for re-enqueuing incoming messages + +When authorizing via PolicyKit we want to process incoming method calls +twice: once to process and figure out that we need PK authentication, +and a second time after we aquired PK authentication to actually execute +the operation. With this new call sd_bus_enqueue_for_read() we have a +way to put an incoming message back into the read queue for this +purpose. + +This might have other uses too, for example debugging. +Related: CVE-2020-1712 +--- + src/libsystemd/libsystemd.sym | 1 + + src/libsystemd/sd-bus/sd-bus.c | 24 ++++++++++++++++++++++++ + src/systemd/sd-bus.h | 1 + + 3 files changed, 26 insertions(+) + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index 1eec17db50..e9972593a6 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -569,4 +569,5 @@ global: + sd_event_source_get_inotify_mask; + sd_event_source_set_destroy_callback; + sd_event_source_get_destroy_callback; ++ sd_bus_enqueue_for_read; + } LIBSYSTEMD_238; +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index e49d58137d..68ad6cbe89 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -4120,3 +4120,27 @@ _public_ int sd_bus_get_n_queued_write(sd_bus *bus, uint64_t *ret) { + *ret = bus->wqueue_size; + return 0; + } ++ ++_public_ int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m) { ++ int r; ++ ++ assert_return(bus, -EINVAL); ++ assert_return(bus = bus_resolve(bus), -ENOPKG); ++ assert_return(m, -EINVAL); ++ assert_return(m->sealed, -EINVAL); ++ assert_return(!bus_pid_changed(bus), -ECHILD); ++ ++ if (!BUS_IS_OPEN(bus->state)) ++ return -ENOTCONN; ++ ++ /* Re-enqeue a message for reading. This is primarily useful for PolicyKit-style authentication, ++ * where we want accept a message, then determine we need to interactively authenticate the user, and ++ * when we have that process the message again. */ ++ ++ r = bus_rqueue_make_room(bus); ++ if (r < 0) ++ return r; ++ ++ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(m, bus); ++ return 0; ++} +diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h +index 54c4b1ca83..9ba757b13d 100644 +--- a/src/systemd/sd-bus.h ++++ b/src/systemd/sd-bus.h +@@ -193,6 +193,7 @@ int sd_bus_process(sd_bus *bus, sd_bus_message **r); + int sd_bus_process_priority(sd_bus *bus, int64_t max_priority, sd_bus_message **r); + int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec); + int sd_bus_flush(sd_bus *bus); ++int sd_bus_enqueue_for_read(sd_bus *bus, sd_bus_message *m); + + sd_bus_slot* sd_bus_get_current_slot(sd_bus *bus); + sd_bus_message* sd_bus_get_current_message(sd_bus *bus); diff --git a/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch b/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch new file mode 100644 index 0000000..9ff72ce --- /dev/null +++ b/SOURCES/0237-sd-event-add-sd_event_source_disable_unref-helper.patch @@ -0,0 +1,130 @@ +From 8e155b3dad29a96cd2586185c63604c42bc5690e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 8 May 2019 14:39:57 +0200 +Subject: [PATCH] sd-event: add sd_event_source_disable_unref() helper + +(cherry picked from commit afd15bbb4b6414b9356799c63029e36642dae8e4) +Related: CVE-2020-1712 +--- + man/rules/meson.build | 4 +++- + man/sd_event_source_unref.xml | 30 +++++++++++++++++++----------- + src/libsystemd/libsystemd.sym | 1 + + src/libsystemd/sd-event/sd-event.c | 6 ++++++ + src/systemd/sd-event.h | 1 + + 5 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/man/rules/meson.build b/man/rules/meson.build +index 989d11c9b9..7ae94ea265 100644 +--- a/man/rules/meson.build ++++ b/man/rules/meson.build +@@ -340,7 +340,9 @@ manpages = [ + ['sd_event_source_set_userdata', '3', ['sd_event_source_get_userdata'], ''], + ['sd_event_source_unref', + '3', +- ['sd_event_source_ref', 'sd_event_source_unrefp'], ++ ['sd_event_source_disable_unref', ++ 'sd_event_source_ref', ++ 'sd_event_source_unrefp'], + ''], + ['sd_event_wait', + '3', +diff --git a/man/sd_event_source_unref.xml b/man/sd_event_source_unref.xml +index d1b83c57aa..af8fed33f2 100644 +--- a/man/sd_event_source_unref.xml ++++ b/man/sd_event_source_unref.xml +@@ -22,6 +22,7 @@ + sd_event_source_unref + sd_event_source_unrefp + sd_event_source_ref ++ sd_event_source_disable_unref + + Increase or decrease event source reference counters + +@@ -45,6 +46,10 @@ + sd_event_source *source + + ++ ++ sd_event_source* sd_event_source_disable_unref ++ sd_event_source *source ++ + + + +@@ -80,23 +85,26 @@ + the passed event source object is + NULL. + +- Note that event source objects stay alive and may be +- dispatched as long as they have a reference counter greater than +- zero. In order to drop a reference of an event source and make +- sure the associated event source handler function is not called +- anymore it is recommended to combine a call of ++ Note that event source objects stay alive and may be dispatched as long as they have a reference ++ counter greater than zero. In order to drop a reference of an event source and make sure the associated ++ event source handler function is not called anymore it is recommended to combine a call of + sd_event_source_unref() with a prior call to +- sd_event_source_set_enabled() with +- SD_EVENT_OFF. ++ sd_event_source_set_enabled() with SD_EVENT_OFF or call ++ sd_event_source_disable_unref(), see below. ++ ++ sd_event_source_disable_unref() combines a call to ++ sd_event_source_set_enabled() with SD_EVENT_OFF with ++ sd_event_source_unref(). This ensures that the source is disabled before the local ++ reference to it is lost. The source parameter is allowed to be ++ NULL. + + + + Return Value + +- sd_event_source_unref() always returns +- NULL. +- sd_event_source_ref() always returns the +- event source object passed in. ++ sd_event_source_unref() and ++ sd_event_source_disable_unref() always return NULL. ++ sd_event_source_ref() always returns the event source object passed in. + + + +diff --git a/src/libsystemd/libsystemd.sym b/src/libsystemd/libsystemd.sym +index e9972593a6..778e88a16c 100644 +--- a/src/libsystemd/libsystemd.sym ++++ b/src/libsystemd/libsystemd.sym +@@ -570,4 +570,5 @@ global: + sd_event_source_set_destroy_callback; + sd_event_source_get_destroy_callback; + sd_bus_enqueue_for_read; ++ sd_event_source_disable_unref; + } LIBSYSTEMD_238; +diff --git a/src/libsystemd/sd-event/sd-event.c b/src/libsystemd/sd-event/sd-event.c +index d53b9a7026..0d3bf5cbb6 100644 +--- a/src/libsystemd/sd-event/sd-event.c ++++ b/src/libsystemd/sd-event/sd-event.c +@@ -580,6 +580,12 @@ _public_ sd_event* sd_event_unref(sd_event *e) { + return NULL; + } + ++_public_ sd_event_source* sd_event_source_disable_unref(sd_event_source *s) { ++ if (s) ++ (void) sd_event_source_set_enabled(s, SD_EVENT_OFF); ++ return sd_event_source_unref(s); ++} ++ + static bool event_pid_changed(sd_event *e) { + assert(e); + +diff --git a/src/systemd/sd-event.h b/src/systemd/sd-event.h +index 7fcae4ac49..9876be01c6 100644 +--- a/src/systemd/sd-event.h ++++ b/src/systemd/sd-event.h +@@ -113,6 +113,7 @@ int sd_event_get_iteration(sd_event *e, uint64_t *ret); + + sd_event_source* sd_event_source_ref(sd_event_source *s); + sd_event_source* sd_event_source_unref(sd_event_source *s); ++sd_event_source* sd_event_source_disable_unref(sd_event_source *s); + + sd_event *sd_event_source_get_event(sd_event_source *s); + void* sd_event_source_get_userdata(sd_event_source *s); diff --git a/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch b/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch new file mode 100644 index 0000000..24c565a --- /dev/null +++ b/SOURCES/0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch @@ -0,0 +1,156 @@ +From ae3cdcd5f8954d020a146c980ed064c21fd21239 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 31 Jan 2020 15:17:25 +0100 +Subject: [PATCH] polkit: when authorizing via PK let's re-resolve + callback/userdata instead of caching it + +Previously, when doing an async PK query we'd store the original +callback/userdata pair and call it again after the PK request is +complete. This is problematic, since PK queries might be slow and in the +meantime the userdata might be released and re-acquired. Let's avoid +this by always traversing through the message handlers so that we always +re-resolve the callback and userdata pair and thus can be sure it's +up-to-date and properly valid. + +Resolves: CVE-2020-1712 +--- + src/shared/bus-util.c | 74 +++++++++++++++++++++++++++++-------------- + 1 file changed, 50 insertions(+), 24 deletions(-) + +diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c +index 2d908eb45c..5ed68429be 100644 +--- a/src/shared/bus-util.c ++++ b/src/shared/bus-util.c +@@ -319,10 +319,10 @@ int bus_test_polkit( + + typedef struct AsyncPolkitQuery { + sd_bus_message *request, *reply; +- sd_bus_message_handler_t callback; +- void *userdata; + sd_bus_slot *slot; ++ + Hashmap *registry; ++ sd_event_source *defer_event_source; + } AsyncPolkitQuery; + + static void async_polkit_query_free(AsyncPolkitQuery *q) { +@@ -338,9 +338,22 @@ static void async_polkit_query_free(AsyncPolkitQuery *q) { + sd_bus_message_unref(q->request); + sd_bus_message_unref(q->reply); + ++ sd_event_source_disable_unref(q->defer_event_source); + free(q); + } + ++static int async_polkit_defer(sd_event_source *s, void *userdata) { ++ AsyncPolkitQuery *q = userdata; ++ ++ assert(s); ++ ++ /* This is called as idle event source after we processed the async polkit reply, hopefully after the ++ * method call we re-enqueued has been properly processed. */ ++ ++ async_polkit_query_free(q); ++ return 0; ++} ++ + static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL; + AsyncPolkitQuery *q = userdata; +@@ -349,19 +362,45 @@ static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_e + assert(reply); + assert(q); + ++ assert(q->slot); + q->slot = sd_bus_slot_unref(q->slot); ++ ++ assert(!q->reply); + q->reply = sd_bus_message_ref(reply); + ++ /* Now, let's dispatch the original message a second time be re-enqueing. This will then traverse the ++ * whole message processing again, and thus re-validating and re-retrieving the "userdata" field ++ * again. ++ * ++ * We install an idle event loop event to clean-up the PolicyKit request data when we are idle again, ++ * i.e. after the second time the message is processed is complete. */ ++ ++ assert(!q->defer_event_source); ++ r = sd_event_add_defer(sd_bus_get_event(sd_bus_message_get_bus(reply)), &q->defer_event_source, async_polkit_defer, q); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_priority(q->defer_event_source, SD_EVENT_PRIORITY_IDLE); ++ if (r < 0) ++ goto fail; ++ ++ r = sd_event_source_set_enabled(q->defer_event_source, SD_EVENT_ONESHOT); ++ if (r < 0) ++ goto fail; ++ + r = sd_bus_message_rewind(q->request, true); +- if (r < 0) { +- r = sd_bus_reply_method_errno(q->request, r, NULL); +- goto finish; +- } ++ if (r < 0) ++ goto fail; + +- r = q->callback(q->request, q->userdata, &error_buffer); +- r = bus_maybe_reply_error(q->request, r, &error_buffer); ++ r = sd_bus_enqueue_for_read(sd_bus_message_get_bus(q->request), q->request); ++ if (r < 0) ++ goto fail; + +-finish: ++ return 1; ++ ++fail: ++ log_debug_errno(r, "Processing asynchronous PolicyKit reply failed, ignoring: %m"); ++ (void) sd_bus_reply_method_errno(q->request, r, NULL); + async_polkit_query_free(q); + + return r; +@@ -382,11 +421,9 @@ int bus_verify_polkit_async( + #if ENABLE_POLKIT + _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL; + AsyncPolkitQuery *q; +- const char *sender, **k, **v; +- sd_bus_message_handler_t callback; +- void *userdata; + int c; + #endif ++ const char *sender, **k, **v; + int r; + + assert(call); +@@ -444,20 +481,11 @@ int bus_verify_polkit_async( + else if (r > 0) + return 1; + +-#if ENABLE_POLKIT +- if (sd_bus_get_current_message(call->bus) != call) +- return -EINVAL; +- +- callback = sd_bus_get_current_handler(call->bus); +- if (!callback) +- return -EINVAL; +- +- userdata = sd_bus_get_current_userdata(call->bus); +- + sender = sd_bus_message_get_sender(call); + if (!sender) + return -EBADMSG; + ++#if ENABLE_POLKIT + c = sd_bus_message_get_allow_interactive_authorization(call); + if (c < 0) + return c; +@@ -509,8 +537,6 @@ int bus_verify_polkit_async( + return -ENOMEM; + + q->request = sd_bus_message_ref(call); +- q->callback = callback; +- q->userdata = userdata; + + r = hashmap_put(*registry, call, q); + if (r < 0) { diff --git a/SOURCES/0239-sd-bus-use-queue-message-references-for-managing-r-w.patch b/SOURCES/0239-sd-bus-use-queue-message-references-for-managing-r-w.patch new file mode 100644 index 0000000..10ff2cd --- /dev/null +++ b/SOURCES/0239-sd-bus-use-queue-message-references-for-managing-r-w.patch @@ -0,0 +1,183 @@ +From ed560bc85cd2537dd083a8995b5d10f66f7a391f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 17 Jan 2019 18:31:59 +0100 +Subject: [PATCH] sd-bus: use "queue" message references for managing r/w + message queues in connection objects + +Let's make use of the new concept the previous commit added. + +See: #4846 +(cherry picked from commit c1757a70eac0382c4837a3833d683919f6a48ed7) +Related: CVE-2020-1712 +--- + src/libsystemd/sd-bus/bus-socket.c | 6 ++- + src/libsystemd/sd-bus/sd-bus.c | 60 ++++++++++++++---------------- + 2 files changed, 32 insertions(+), 34 deletions(-) + +diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c +index 17cfa8e1fd..4a72795d2b 100644 +--- a/src/libsystemd/sd-bus/bus-socket.c ++++ b/src/libsystemd/sd-bus/bus-socket.c +@@ -1116,8 +1116,10 @@ static int bus_socket_make_message(sd_bus *bus, size_t size) { + bus->fds = NULL; + bus->n_fds = 0; + +- if (t) +- bus->rqueue[bus->rqueue_size++] = t; ++ if (t) { ++ bus->rqueue[bus->rqueue_size++] = bus_message_ref_queued(t, bus); ++ sd_bus_message_unref(t); ++ } + + return 1; + } +diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c +index 68ad6cbe89..a3509f7e89 100644 +--- a/src/libsystemd/sd-bus/sd-bus.c ++++ b/src/libsystemd/sd-bus/sd-bus.c +@@ -148,13 +148,13 @@ static void bus_reset_queues(sd_bus *b) { + assert(b); + + while (b->rqueue_size > 0) +- sd_bus_message_unref(b->rqueue[--b->rqueue_size]); ++ bus_message_unref_queued(b->rqueue[--b->rqueue_size], b); + + b->rqueue = mfree(b->rqueue); + b->rqueue_allocated = 0; + + while (b->wqueue_size > 0) +- sd_bus_message_unref(b->wqueue[--b->wqueue_size]); ++ bus_message_unref_queued(b->wqueue[--b->wqueue_size], b); + + b->wqueue = mfree(b->wqueue); + b->wqueue_allocated = 0; +@@ -493,7 +493,7 @@ static int synthesize_connected_signal(sd_bus *bus) { + + /* Insert at the very front */ + memmove(bus->rqueue + 1, bus->rqueue, sizeof(sd_bus_message*) * bus->rqueue_size); +- bus->rqueue[0] = TAKE_PTR(m); ++ bus->rqueue[0] = bus_message_ref_queued(m, bus); + bus->rqueue_size++; + + return 0; +@@ -1760,7 +1760,7 @@ static int dispatch_wqueue(sd_bus *bus) { + * anyway. */ + + bus->wqueue_size--; +- sd_bus_message_unref(bus->wqueue[0]); ++ bus_message_unref_queued(bus->wqueue[0], bus); + memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size); + bus->windex = 0; + +@@ -1789,6 +1789,15 @@ int bus_rqueue_make_room(sd_bus *bus) { + return 0; + } + ++static void rqueue_drop_one(sd_bus *bus, size_t i) { ++ assert(bus); ++ assert(i < bus->rqueue_size); ++ ++ bus_message_unref_queued(bus->rqueue[i], bus); ++ memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); ++ bus->rqueue_size--; ++} ++ + static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd_bus_message **m) { + int r, ret = 0; + +@@ -1803,10 +1812,8 @@ static int dispatch_rqueue(sd_bus *bus, bool hint_priority, int64_t priority, sd + for (;;) { + if (bus->rqueue_size > 0) { + /* Dispatch a queued message */ +- +- *m = bus->rqueue[0]; +- bus->rqueue_size--; +- memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size); ++ *m = sd_bus_message_ref(bus->rqueue[0]); ++ rqueue_drop_one(bus, 0); + return 1; + } + +@@ -1884,7 +1891,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + * of the wqueue array is always allocated so + * that we always can remember how much was + * written. */ +- bus->wqueue[0] = sd_bus_message_ref(m); ++ bus->wqueue[0] = bus_message_ref_queued(m, bus); + bus->wqueue_size = 1; + bus->windex = idx; + } +@@ -1898,7 +1905,7 @@ _public_ int sd_bus_send(sd_bus *bus, sd_bus_message *_m, uint64_t *cookie) { + if (!GREEDY_REALLOC(bus->wqueue, bus->wqueue_allocated, bus->wqueue_size + 1)) + return -ENOMEM; + +- bus->wqueue[bus->wqueue_size++] = sd_bus_message_ref(m); ++ bus->wqueue[bus->wqueue_size++] = bus_message_ref_queued(m, bus); + } + + finish: +@@ -2124,37 +2131,30 @@ _public_ int sd_bus_call( + usec_t left; + + while (i < bus->rqueue_size) { +- sd_bus_message *incoming = NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *incoming = NULL; + +- incoming = bus->rqueue[i]; ++ incoming = sd_bus_message_ref(bus->rqueue[i]); + + if (incoming->reply_cookie == cookie) { + /* Found a match! */ + +- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); +- bus->rqueue_size--; ++ rqueue_drop_one(bus, i); + log_debug_bus_message(incoming); + + if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) { + + if (incoming->n_fds <= 0 || bus->accept_fd) { + if (reply) +- *reply = incoming; +- else +- sd_bus_message_unref(incoming); ++ *reply = TAKE_PTR(incoming); + + return 1; + } + +- r = sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); +- sd_bus_message_unref(incoming); +- return r; ++ return sd_bus_error_setf(error, SD_BUS_ERROR_INCONSISTENT_MESSAGE, "Reply message contained file descriptors which I couldn't accept. Sorry."); + +- } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) { +- r = sd_bus_error_copy(error, &incoming->error); +- sd_bus_message_unref(incoming); +- return r; +- } else { ++ } else if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) ++ return sd_bus_error_copy(error, &incoming->error); ++ else { + r = -EIO; + goto fail; + } +@@ -2164,15 +2164,11 @@ _public_ int sd_bus_call( + incoming->sender && + streq(bus->unique_name, incoming->sender)) { + +- memmove(bus->rqueue + i, bus->rqueue + i + 1, sizeof(sd_bus_message*) * (bus->rqueue_size - i - 1)); +- bus->rqueue_size--; ++ rqueue_drop_one(bus, i); + +- /* Our own message? Somebody is trying +- * to send its own client a message, +- * let's not dead-lock, let's fail +- * immediately. */ ++ /* Our own message? Somebody is trying to send its own client a message, ++ * let's not dead-lock, let's fail immediately. */ + +- sd_bus_message_unref(incoming); + r = -ELOOP; + goto fail; + } diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index e274b08..0d29122 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 18%{?dist}.2 +Release: 18%{?dist}.4 # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -272,6 +272,23 @@ Patch0219: 0219-resolved-do-not-run-loop-twice.patch Patch0220: 0220-resolved-allow-access-to-Set-Link-and-Revert-methods.patch Patch0221: 0221-resolved-query-polkit-only-after-parsing-the-data.patch Patch0222: 0222-ask-password-prevent-buffer-overrow-when-reading-fro.patch +Patch0223: 0223-core-job-fix-breakage-of-ordering-dependencies-by-sy.patch +Patch0224: 0224-syslog-fix-segfault-in-syslog_parse_priority.patch +Patch0225: 0225-journald-fixed-assertion-failure-when-system-journal.patch +Patch0226: 0226-test-use-PBKDF2-instead-of-Argon2-in-cryptsetup.patch +Patch0227: 0227-test-mask-several-unnecessary-services.patch +Patch0228: 0228-test-bump-the-second-partition-s-size-to-50M.patch +Patch0229: 0229-sd-bus-make-rqueue-wqueue-sizes-of-type-size_t.patch +Patch0230: 0230-sd-bus-reorder-bus-ref-and-bus-message-ref-handling.patch +Patch0231: 0231-sd-bus-make-sure-dispatch_rqueue-initializes-return-.patch +Patch0232: 0232-sd-bus-drop-two-inappropriate-empty-lines.patch +Patch0233: 0233-sd-bus-initialize-mutex-after-we-allocated-the-wqueu.patch +Patch0234: 0234-sd-bus-always-go-through-sd_bus_unref-to-free-messag.patch +Patch0235: 0235-bus-message-introduce-two-kinds-of-references-to-bus.patch +Patch0236: 0236-sd-bus-introduce-API-for-re-enqueuing-incoming-messa.patch +Patch0237: 0237-sd-event-add-sd_event_source_disable_unref-helper.patch +Patch0238: 0238-polkit-when-authorizing-via-PK-let-s-re-resolve-call.patch +Patch0239: 0239-sd-bus-use-queue-message-references-for-managing-r-w.patch %ifarch %{ix86} x86_64 aarch64 @@ -891,6 +908,27 @@ fi %files tests -f .file-list-tests %changelog +* Thu Feb 13 2020 systemd maintenance team - 239-18.4 +- sd-bus: use "queue" message references for managing r/w message queues in connection objects (CVE-2020-1712) + +* Mon Feb 03 2020 systemd maintenance team - 239-18.3 +- core, job: fix breakage of ordering dependencies by systemctl reload command (#1781712) +- syslog: fix segfault in syslog_parse_priority() (#1781712) +- journald: fixed assertion failure when system journal rotation fails (#9893) (#1781712) +- test: use PBKDF2 instead of Argon2 in cryptsetup... (#1781712) +- test: mask several unnecessary services (#1781712) +- test: bump the second partition's size to 50M (#1781712) +- sd-bus: make rqueue/wqueue sizes of type size_t (#20201712) +- sd-bus: reorder bus ref and bus message ref handling (#20201712) +- sd-bus: make sure dispatch_rqueue() initializes return parameter on all types of success (#20201712) +- sd-bus: drop two inappropriate empty lines (#20201712) +- sd-bus: initialize mutex after we allocated the wqueue (#20201712) +- sd-bus: always go through sd_bus_unref() to free messages (#20201712) +- bus-message: introduce two kinds of references to bus messages (#20201712) +- sd-bus: introduce API for re-enqueuing incoming messages (#20201712) +- sd-event: add sd_event_source_disable_unref() helper (#20201712) +- polkit: when authorizing via PK let's re-resolve callback/userdata instead of caching it (#20201712) + * Fri Nov 29 2019 systemd maintenance team - 239-18.2 - ask-password: prevent buffer overrow when reading from keyring (#1777037)