diff --git a/SOURCES/0614-tmpfiles-don-t-skip-cleanup-of-read-only-root-owned-.patch b/SOURCES/0614-tmpfiles-don-t-skip-cleanup-of-read-only-root-owned-.patch new file mode 100644 index 00000000..67a051a9 --- /dev/null +++ b/SOURCES/0614-tmpfiles-don-t-skip-cleanup-of-read-only-root-owned-.patch @@ -0,0 +1,41 @@ +From 38c68c3b13e278a77a4bd02d97f6b3f81db46288 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 27 Mar 2018 10:34:06 +0200 +Subject: [PATCH] tmpfiles: don't skip cleanup of read-only root owned files if + TMPFILES_AGE_ALL is set + +Resolves: #1533638 +--- + src/tmpfiles/tmpfiles.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index ddb274fce..5212d72f5 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -367,6 +367,7 @@ static int dir_cleanup( + struct stat s; + usec_t age; + _cleanup_free_ char *sub_path = NULL; ++ const char *e; + + if (STR_IN_SET(dent->d_name, ".", "..")) + continue; +@@ -399,10 +400,13 @@ static int dir_cleanup( + continue; + } + +- /* Do not delete read-only files owned by root */ +- if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) { +- log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name); +- continue; ++ e = getenv("TMPFILES_AGE_ALL"); ++ if (!e) { ++ /* Do not delete read-only files owned by root */ ++ if (s.st_uid == 0 && !(s.st_mode & S_IWUSR)) { ++ log_debug("Ignoring \"%s/%s\": read-only and owner by root.", p, dent->d_name); ++ continue; ++ } + } + + sub_path = strjoin(p, "/", dent->d_name, NULL); diff --git a/SOURCES/0615-timer-we-already-got-the-trigger-before-no-need-to-c.patch b/SOURCES/0615-timer-we-already-got-the-trigger-before-no-need-to-c.patch new file mode 100644 index 00000000..7af159f3 --- /dev/null +++ b/SOURCES/0615-timer-we-already-got-the-trigger-before-no-need-to-c.patch @@ -0,0 +1,28 @@ +From cfa30c21a4e5324a43695fcf43fe984aed2a8a8e Mon Sep 17 00:00:00 2001 +From: Lukas Nykryn +Date: Mon, 26 Feb 2018 13:56:52 +0100 +Subject: [PATCH] timer: we already got the trigger before, no need to call + UNIT_TRIGGER again + +In d7b2f6ef we forgot to replace this occurence. + +rhel-only + +Resolves: #1549119 +--- + src/core/timer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 91d8db67e..0a264f60d 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -421,7 +421,7 @@ static void timer_enter_waiting(Timer *t, bool initial) { + + case TIMER_UNIT_INACTIVE: + +- base = UNIT_TRIGGER(UNIT(t))->inactive_enter_timestamp.monotonic; ++ base = trigger->inactive_enter_timestamp.monotonic; + + if (base <= 0) + base = t->last_trigger.monotonic; diff --git a/SOURCES/0616-doc-fix-links-to-binfmt_misc-kernel-documentation.patch b/SOURCES/0616-doc-fix-links-to-binfmt_misc-kernel-documentation.patch new file mode 100644 index 00000000..4440ceca --- /dev/null +++ b/SOURCES/0616-doc-fix-links-to-binfmt_misc-kernel-documentation.patch @@ -0,0 +1,79 @@ +From fdc7b6b2af0b80e13bebae8d2f461f54cb71c9d2 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 27 Apr 2018 08:57:08 +0200 +Subject: [PATCH] doc: fix links to binfmt_misc kernel documentation + +Resolves: #1572244 +--- + man/binfmt.d.xml | 2 +- + src/test/test-util.c | 2 +- + units/proc-sys-fs-binfmt_misc.automount | 2 +- + units/proc-sys-fs-binfmt_misc.mount | 2 +- + units/systemd-binfmt.service.in | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/man/binfmt.d.xml b/man/binfmt.d.xml +index 5b63cfb4c..1a57517d0 100644 +--- a/man/binfmt.d.xml ++++ b/man/binfmt.d.xml +@@ -67,7 +67,7 @@ + + Each file contains a list of binfmt_misc kernel binary + format rules. Consult binfmt_misc.txt ++ url="https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst">binfmt_misc.rst + for more information on registration of additional binary formats + and how to write rules. + +diff --git a/src/test/test-util.c b/src/test/test-util.c +index fcf5416c0..f2c52edce 100644 +--- a/src/test/test-util.c ++++ b/src/test/test-util.c +@@ -1213,7 +1213,7 @@ static void test_files_same(void) { + + static void test_is_valid_documentation_url(void) { + assert_se(documentation_url_is_valid("http://www.freedesktop.org/wiki/Software/systemd")); +- assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/binfmt_misc.txt")); ++ assert_se(documentation_url_is_valid("https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst")); + assert_se(documentation_url_is_valid("file:/foo/foo")); + assert_se(documentation_url_is_valid("man:systemd.special(7)")); + assert_se(documentation_url_is_valid("info:bar")); +diff --git a/units/proc-sys-fs-binfmt_misc.automount b/units/proc-sys-fs-binfmt_misc.automount +index 6be38937b..b28bf9bb8 100644 +--- a/units/proc-sys-fs-binfmt_misc.automount ++++ b/units/proc-sys-fs-binfmt_misc.automount +@@ -7,7 +7,7 @@ + + [Unit] + Description=Arbitrary Executable File Formats File System Automount Point +-Documentation=https://www.kernel.org/doc/Documentation/binfmt_misc.txt ++Documentation=https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst + Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems + DefaultDependencies=no + Before=sysinit.target +diff --git a/units/proc-sys-fs-binfmt_misc.mount b/units/proc-sys-fs-binfmt_misc.mount +index 8c7c38631..8d22dc908 100644 +--- a/units/proc-sys-fs-binfmt_misc.mount ++++ b/units/proc-sys-fs-binfmt_misc.mount +@@ -7,7 +7,7 @@ + + [Unit] + Description=Arbitrary Executable File Formats File System +-Documentation=https://www.kernel.org/doc/Documentation/binfmt_misc.txt ++Documentation=https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst + Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems + DefaultDependencies=no + +diff --git a/units/systemd-binfmt.service.in b/units/systemd-binfmt.service.in +index 02dfe774d..e066f7fec 100644 +--- a/units/systemd-binfmt.service.in ++++ b/units/systemd-binfmt.service.in +@@ -8,7 +8,7 @@ + [Unit] + Description=Set Up Additional Binary Formats + Documentation=man:systemd-binfmt.service(8) man:binfmt.d(5) +-Documentation=https://www.kernel.org/doc/Documentation/binfmt_misc.txt ++Documentation=https://www.kernel.org/doc/Documentation/admin-guide/binfmt-misc.rst + DefaultDependencies=no + Conflicts=shutdown.target + After=systemd-readahead-collect.service systemd-readahead-replay.service proc-sys-fs-binfmt_misc.automount diff --git a/SOURCES/0617-man-udevadm-remove-superfluous-version-from-subcomma.patch b/SOURCES/0617-man-udevadm-remove-superfluous-version-from-subcomma.patch new file mode 100644 index 00000000..cc5cc2df --- /dev/null +++ b/SOURCES/0617-man-udevadm-remove-superfluous-version-from-subcomma.patch @@ -0,0 +1,27 @@ +From 5fa3a659c5d106734b3fa76270f048b8b2ea0194 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 23 Mar 2018 11:20:31 +0100 +Subject: [PATCH] man/udevadm: remove superfluous --version from subcommand + +Resolves: #1553076 +--- + man/udevadm.xml | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/man/udevadm.xml b/man/udevadm.xml +index 8ef9e23aa..99eae387f 100644 +--- a/man/udevadm.xml ++++ b/man/udevadm.xml +@@ -187,12 +187,6 @@ + Cleanup the udev database. + + +- +- +- +- Print version. +- +- + + + diff --git a/SOURCES/0618-man-udevadm-correctly-show-the-short-version-of-exit.patch b/SOURCES/0618-man-udevadm-correctly-show-the-short-version-of-exit.patch new file mode 100644 index 00000000..f367e877 --- /dev/null +++ b/SOURCES/0618-man-udevadm-correctly-show-the-short-version-of-exit.patch @@ -0,0 +1,23 @@ +From 81725f613bebedc27f7ff763097bcb393f9c4bd9 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Wed, 7 Mar 2018 18:45:29 +0100 +Subject: [PATCH] man/udevadm: correctly show the short version of --exit + +Resolves: #1552712 +--- + man/udevadm.xml | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/man/udevadm.xml b/man/udevadm.xml +index 99eae387f..e11c2cb2e 100644 +--- a/man/udevadm.xml ++++ b/man/udevadm.xml +@@ -374,7 +374,7 @@ + Modify the internal state of the running udev daemon. + + +- ++ + + + Signal and wait for systemd-udevd to exit. diff --git a/SOURCES/0619-core-timer-downgrade-message-about-random-time-addit.patch b/SOURCES/0619-core-timer-downgrade-message-about-random-time-addit.patch new file mode 100644 index 00000000..e7a22569 --- /dev/null +++ b/SOURCES/0619-core-timer-downgrade-message-about-random-time-addit.patch @@ -0,0 +1,30 @@ +From 7adabea503fb86b3b33da17fe65a2b5a246fcac7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sun, 5 Feb 2017 03:37:46 -0500 +Subject: [PATCH] core/timer: downgrade message about random time addition + (#5229) + +This seems like something that shouldn't be higher then debug level, even +if it does not get emitted too often. + +Fixes #5228. + +(cherry picked from commit 382852fd581efe3cc0ae11154102ab9f435adea1) +Resolves: #1587906 +--- + src/core/timer.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/timer.c b/src/core/timer.c +index 0a264f60d..d32b007c7 100644 +--- a/src/core/timer.c ++++ b/src/core/timer.c +@@ -335,7 +335,7 @@ static void add_random(Timer *t, usec_t *v) { + else + *v += add; + +- log_unit_info(UNIT(t)->id, "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); ++ log_unit_debug(UNIT(t)->id, "Adding %s random time.", format_timespan(s, sizeof(s), add, 0)); + } + + static void timer_enter_waiting(Timer *t, bool initial) { diff --git a/SOURCES/0620-fd-util-add-new-acquire_data_fd-API-helper.patch b/SOURCES/0620-fd-util-add-new-acquire_data_fd-API-helper.patch new file mode 100644 index 00000000..af8d1874 --- /dev/null +++ b/SOURCES/0620-fd-util-add-new-acquire_data_fd-API-helper.patch @@ -0,0 +1,277 @@ +From 581edd240f8dd68b1dbb4070353ddb2059eb8a67 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 27 Oct 2017 10:56:42 +0200 +Subject: [PATCH] fd-util: add new acquire_data_fd() API helper + +All this function does is place some data in an in-memory read-only fd, +that may be read back to get the original data back. + +Doing this in a way that works everywhere, given the different kernels +we support as well as different privilege levels is surprisingly +complex. + +(cherry picked from commit a548e14d690133dd8cca2d5ab8082bb23259fd5f) + +Related: #1446095 +--- + src/shared/util.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ + src/shared/util.h | 10 ++++ + src/test/test-util.c | 49 ++++++++++++++++ + 3 files changed, 215 insertions(+) + +diff --git a/src/shared/util.c b/src/shared/util.c +index af0953273..982f5e044 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -95,6 +95,7 @@ + #include "sparse-endian.h" + #include "conf-parser.h" + #include "cgroup-util.h" ++#include "memfd-util.h" + + int saved_argc = 0; + char **saved_argv = NULL; +@@ -8893,3 +8894,158 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max) { + + return m / max; + } ++ ++int acquire_data_fd(const void *data, size_t size, unsigned flags) { ++ ++ char procfs_path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int)]; ++ _cleanup_close_pair_ int pipefds[2] = { -1, -1 }; ++ char pattern[] = "/dev/shm/data-fd-XXXXXX"; ++ _cleanup_close_ int fd = -1; ++ int isz = 0, r; ++ ssize_t n; ++ off_t f; ++ ++ assert(data || size == 0); ++ ++ /* Acquire a read-only file descriptor that when read from returns the specified data. This is much more ++ * complex than I wish it was. But here's why: ++ * ++ * a) First we try to use memfds. They are the best option, as we can seal them nicely to make them ++ * read-only. Unfortunately they require kernel 3.17, and – at the time of writing – we still support 3.14. ++ * ++ * b) Then, we try classic pipes. They are the second best options, as we can close the writing side, retaining ++ * a nicely read-only fd in the reading side. However, they are by default quite small, and unprivileged ++ * clients can only bump their size to a system-wide limit, which might be quite low. ++ * ++ * c) Then, we try an O_TMPFILE file in /dev/shm (that dir is the only suitable one known to exist from ++ * earliest boot on). To make it read-only we open the fd a second time with O_RDONLY via ++ * /proc/self/. Unfortunately O_TMPFILE is not available on older kernels on tmpfs. ++ * ++ * d) Finally, we try creating a regular file in /dev/shm, which we then delete. ++ * ++ * It sucks a bit that depending on the situation we return very different objects here, but that's Linux I ++ * figure. */ ++ ++ if (size == 0 && ((flags & ACQUIRE_NO_DEV_NULL) == 0)) { ++ /* As a special case, return /dev/null if we have been called for an empty data block */ ++ r = open("/dev/null", O_RDONLY|O_CLOEXEC|O_NOCTTY); ++ if (r < 0) ++ return -errno; ++ ++ return r; ++ } ++ ++ if ((flags & ACQUIRE_NO_MEMFD) == 0) { ++ fd = memfd_new("data-fd"); ++ if (fd < 0) ++ goto try_pipe; ++ ++ n = write(fd, data, size); ++ if (n < 0) ++ return -errno; ++ if ((size_t) n != size) ++ return -EIO; ++ ++ f = lseek(fd, 0, SEEK_SET); ++ if (f != 0) ++ return -errno; ++ ++ r = memfd_set_sealed(fd); ++ if (r < 0) ++ return r; ++ ++ r = fd; ++ fd = -1; ++ ++ return r; ++ } ++ ++try_pipe: ++ if ((flags & ACQUIRE_NO_PIPE) == 0) { ++ if (pipe2(pipefds, O_CLOEXEC|O_NONBLOCK) < 0) ++ return -errno; ++ ++ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); ++ if (isz < 0) ++ return -errno; ++ ++ if ((size_t) isz < size) { ++ isz = (int) size; ++ if (isz < 0 || (size_t) isz != size) ++ return -E2BIG; ++ ++ /* Try to bump the pipe size */ ++ (void) fcntl(pipefds[1], F_SETPIPE_SZ, isz); ++ ++ /* See if that worked */ ++ isz = fcntl(pipefds[1], F_GETPIPE_SZ, 0); ++ if (isz < 0) ++ return -errno; ++ ++ if ((size_t) isz < size) ++ goto try_dev_shm; ++ } ++ ++ n = write(pipefds[1], data, size); ++ if (n < 0) ++ return -errno; ++ if ((size_t) n != size) ++ return -EIO; ++ ++ (void) fd_nonblock(pipefds[0], false); ++ ++ r = pipefds[0]; ++ pipefds[0] = -1; ++ ++ return r; ++ } ++ ++try_dev_shm: ++ if ((flags & ACQUIRE_NO_TMPFILE) == 0) { ++ fd = open("/dev/shm", O_RDWR|O_TMPFILE|O_CLOEXEC, 0500); ++ if (fd < 0) ++ goto try_dev_shm_without_o_tmpfile; ++ ++ n = write(fd, data, size); ++ if (n < 0) ++ return -errno; ++ if ((size_t) n != size) ++ return -EIO; ++ ++ /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ ++ xsprintf(procfs_path, "/proc/self/fd/%i", fd); ++ r = open(procfs_path, O_RDONLY|O_CLOEXEC); ++ if (r < 0) ++ return -errno; ++ ++ return r; ++ } ++ ++try_dev_shm_without_o_tmpfile: ++ if ((flags & ACQUIRE_NO_REGULAR) == 0) { ++ fd = mkostemp_safe(pattern, O_CLOEXEC); ++ if (fd < 0) ++ return fd; ++ ++ n = write(fd, data, size); ++ if (n < 0) { ++ r = -errno; ++ goto unlink_and_return; ++ } ++ if ((size_t) n != size) { ++ r = -EIO; ++ goto unlink_and_return; ++ } ++ ++ /* Let's reopen the thing, in order to get an O_RDONLY fd for the original O_RDWR one */ ++ r = open(pattern, O_RDONLY|O_CLOEXEC); ++ if (r < 0) ++ r = -errno; ++ ++ unlink_and_return: ++ (void) unlink(pattern); ++ return r; ++ } ++ ++ return -EOPNOTSUPP; ++} +diff --git a/src/shared/util.h b/src/shared/util.h +index 526a6fe84..9c4be0256 100644 +--- a/src/shared/util.h ++++ b/src/shared/util.h +@@ -1112,3 +1112,13 @@ int parse_percent(const char *p); + + uint64_t system_tasks_max(void); + uint64_t system_tasks_max_scale(uint64_t v, uint64_t max); ++ ++enum { ++ ACQUIRE_NO_DEV_NULL = 1 << 0, ++ ACQUIRE_NO_MEMFD = 1 << 1, ++ ACQUIRE_NO_PIPE = 1 << 2, ++ ACQUIRE_NO_TMPFILE = 1 << 3, ++ ACQUIRE_NO_REGULAR = 1 << 4, ++}; ++ ++int acquire_data_fd(const void *data, size_t size, unsigned flags); +diff --git a/src/test/test-util.c b/src/test/test-util.c +index f2c52edce..efb02ff53 100644 +--- a/src/test/test-util.c ++++ b/src/test/test-util.c +@@ -1861,6 +1861,54 @@ static void test_system_tasks_max_scale(void) { + assert_se(system_tasks_max_scale(UINT64_MAX/4, UINT64_MAX) == UINT64_MAX); + } + ++static void test_acquire_data_fd_one(unsigned flags) { ++ char wbuffer[196*1024 - 7]; ++ char rbuffer[sizeof(wbuffer)]; ++ int fd; ++ ++ fd = acquire_data_fd("foo", 3, flags); ++ assert_se(fd >= 0); ++ ++ zero(rbuffer); ++ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 3); ++ assert_se(streq(rbuffer, "foo")); ++ ++ fd = safe_close(fd); ++ ++ fd = acquire_data_fd("", 0, flags); ++ assert_se(fd >= 0); ++ ++ zero(rbuffer); ++ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == 0); ++ assert_se(streq(rbuffer, "")); ++ ++ fd = safe_close(fd); ++ ++ random_bytes(wbuffer, sizeof(wbuffer)); ++ ++ fd = acquire_data_fd(wbuffer, sizeof(wbuffer), flags); ++ assert_se(fd >= 0); ++ ++ zero(rbuffer); ++ assert_se(read(fd, rbuffer, sizeof(rbuffer)) == sizeof(rbuffer)); ++ assert_se(memcmp(rbuffer, wbuffer, sizeof(rbuffer)) == 0); ++ ++ fd = safe_close(fd); ++} ++ ++static void test_acquire_data_fd(void) { ++ ++ test_acquire_data_fd_one(0); ++ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL); ++ test_acquire_data_fd_one(ACQUIRE_NO_MEMFD); ++ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD); ++ test_acquire_data_fd_one(ACQUIRE_NO_PIPE); ++ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_PIPE); ++ test_acquire_data_fd_one(ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE); ++ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE); ++ test_acquire_data_fd_one(ACQUIRE_NO_DEV_NULL|ACQUIRE_NO_MEMFD|ACQUIRE_NO_PIPE|ACQUIRE_NO_TMPFILE); ++} ++ + int main(int argc, char *argv[]) { + log_parse_environment(); + log_open(); +@@ -1943,6 +1991,7 @@ int main(int argc, char *argv[]) { + test_shell_maybe_quote(); + test_system_tasks_max(); + test_system_tasks_max_scale(); ++ test_acquire_data_fd(); + + return 0; + } diff --git a/SOURCES/0621-systemd-analyze-make-dump-work-for-large-of-units.patch b/SOURCES/0621-systemd-analyze-make-dump-work-for-large-of-units.patch new file mode 100644 index 00000000..d62c2e6c --- /dev/null +++ b/SOURCES/0621-systemd-analyze-make-dump-work-for-large-of-units.patch @@ -0,0 +1,189 @@ +From 6772555b226a116bff07b7d8af28b16032273866 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Wed, 9 May 2018 09:35:52 +0200 +Subject: [PATCH] systemd-analyze: make dump work for large # of units + +If there is a large number of units, the size of the generated dump +string can overstep DBus message size limit. So let's pass that string +via a fd. + +(cherry picked from commit c0a1bfacfea9c65ea79fd07682a5b60b5d711a33) + +Resolves: #1446095 +--- + src/analyze/analyze.c | 57 ++++++++++++++++++++++++++++------ + src/core/dbus-manager.c | 26 ++++++++++++++-- + src/core/org.freedesktop.systemd1.conf | 4 +++ + 3 files changed, 76 insertions(+), 11 deletions(-) + +diff --git a/src/analyze/analyze.c b/src/analyze/analyze.c +index ff84f6894..7116aaa88 100644 +--- a/src/analyze/analyze.c ++++ b/src/analyze/analyze.c +@@ -29,6 +29,7 @@ + #include "sd-bus.h" + #include "bus-util.h" + #include "bus-error.h" ++#include "copy.h" + #include "install.h" + #include "log.h" + #include "build.h" +@@ -1096,12 +1097,42 @@ static int dot(sd_bus *bus, char* patterns[]) { + return 0; + } + +-static int dump(sd_bus *bus, char **args) { +- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; +- _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; ++static int dump_fallback(sd_bus *bus) { ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; + const char *text = NULL; + int r; + ++ assert(bus); ++ ++ r = sd_bus_call_method( ++ bus, ++ "org.freedesktop.systemd1", ++ "/org/freedesktop/systemd1", ++ "org.freedesktop.systemd1.Manager", ++ "Dump", ++ &error, ++ &reply, ++ ""); ++ if (r < 0) { ++ log_error("Failed to issue method call Dump: %s", bus_error_message(&error, -r)); ++ return r; ++ } ++ ++ r = sd_bus_message_read(reply, "s", &text); ++ if (r < 0) ++ return bus_log_parse_error(r); ++ ++ fputs(text, stdout); ++ return 0; ++} ++ ++static int dump(sd_bus *bus, char **args) { ++ _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; ++ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; ++ int fd = -1; ++ int r; ++ + if (!strv_isempty(args)) { + log_error("Too many arguments."); + return -E2BIG; +@@ -1109,26 +1140,34 @@ static int dump(sd_bus *bus, char **args) { + + pager_open_if_enabled(); + ++ if (!sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD)) ++ return dump_fallback(bus); ++ + r = sd_bus_call_method( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", +- "Dump", ++ "DumpByFileDescriptor", + &error, + &reply, + ""); + if (r < 0) { +- log_error("Failed issue method call: %s", bus_error_message(&error, -r)); +- return r; ++ /* fall back to Dump if DumpByFileDescriptor is not supported */ ++ if (!IN_SET(r, -EACCES, -EBADR)) { ++ log_error("Failed to issue method call DumpByFileDescriptor: %s", bus_error_message(&error, -r)); ++ return r; ++ } ++ ++ return dump_fallback(bus); + } + +- r = sd_bus_message_read(reply, "s", &text); ++ r = sd_bus_message_read(reply, "h", &fd); + if (r < 0) + return bus_log_parse_error(r); + +- fputs(text, stdout); +- return 0; ++ fflush(stdout); ++ return copy_bytes(fd, STDOUT_FILENO, (uint64_t) -1, 0); + } + + static int set_log_level(sd_bus *bus, char **args) { +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index d34ed042f..1766163b3 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -1064,7 +1064,7 @@ static int method_unsubscribe(sd_bus *bus, sd_bus_message *message, void *userda + return sd_bus_reply_method_return(message, NULL); + } + +-static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { ++static int dump_impl(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error, int (*reply)(sd_bus_message *, char *)) { + _cleanup_free_ char *dump = NULL; + _cleanup_fclose_ FILE *f = NULL; + Manager *m = userdata; +@@ -1089,13 +1089,34 @@ static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_ + manager_dump_jobs(m, f, NULL); + + fflush(f); +- + if (ferror(f)) + return -ENOMEM; + ++ return reply(message, dump); ++} ++ ++static int reply_dump(sd_bus_message *message, char *dump) { + return sd_bus_reply_method_return(message, "s", dump); + } + ++static int method_dump(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { ++ return dump_impl(bus, message, userdata, error, reply_dump); ++} ++ ++static int reply_dump_by_fd(sd_bus_message *message, char *dump) { ++ _cleanup_close_ int fd = -1; ++ ++ fd = acquire_data_fd(dump, strlen(dump), 0); ++ if (fd < 0) ++ return fd; ++ ++ return sd_bus_reply_method_return(message, "h", fd); ++} ++ ++static int method_dump_by_fd(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { ++ return dump_impl(bus, message, userdata, error, reply_dump_by_fd); ++} ++ + static int method_create_snapshot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; +@@ -2092,6 +2113,7 @@ const sd_bus_vtable bus_manager_vtable[] = { + SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED), ++ SD_BUS_METHOD("DumpByFileDescriptor", NULL, "h", method_dump_by_fd, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0), + SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0), + SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED), +diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf +index 3997dd0b4..8187cf173 100644 +--- a/src/core/org.freedesktop.systemd1.conf ++++ b/src/core/org.freedesktop.systemd1.conf +@@ -96,6 +96,10 @@ + send_interface="org.freedesktop.systemd1.Manager" + send_member="Dump"/> + ++ ++ + diff --git a/SOURCES/0622-use-max.-message-size-allowed-by-DBus-spec-8936.patch b/SOURCES/0622-use-max.-message-size-allowed-by-DBus-spec-8936.patch new file mode 100644 index 00000000..18fbab6a --- /dev/null +++ b/SOURCES/0622-use-max.-message-size-allowed-by-DBus-spec-8936.patch @@ -0,0 +1,27 @@ +From 191e504e9847ba3f46fe579922bbee64f02a04c1 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Wed, 9 May 2018 10:33:28 +0200 +Subject: [PATCH] use max. message size allowed by DBus spec (#8936) + +C.f. https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages. + +(cherry picked from commit 33d8fe60573dd3e88fe98e368437bb4d29534b5a) + +Related: #1446095 +--- + src/libsystemd/sd-bus/bus-internal.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/libsystemd/sd-bus/bus-internal.h b/src/libsystemd/sd-bus/bus-internal.h +index 6a106862e..9c1e5a35b 100644 +--- a/src/libsystemd/sd-bus/bus-internal.h ++++ b/src/libsystemd/sd-bus/bus-internal.h +@@ -329,7 +329,7 @@ struct sd_bus { + #define BUS_WQUEUE_MAX (192*1024) + #define BUS_RQUEUE_MAX (192*1024) + +-#define BUS_MESSAGE_SIZE_MAX (64*1024*1024) ++#define BUS_MESSAGE_SIZE_MAX (128*1024*1024) + #define BUS_AUTH_SIZE_MAX (64*1024) + + #define BUS_CONTAINER_DEPTH 128 diff --git a/SOURCES/0623-cryptsetup-support-LUKS2-on-disk-format.patch b/SOURCES/0623-cryptsetup-support-LUKS2-on-disk-format.patch new file mode 100644 index 00000000..a6fd5b41 --- /dev/null +++ b/SOURCES/0623-cryptsetup-support-LUKS2-on-disk-format.patch @@ -0,0 +1,77 @@ +From be973ab9f6585be762ea0888c81b011222eabb13 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Thu, 3 May 2018 11:21:27 +0200 +Subject: [PATCH] cryptsetup: support LUKS2 on-disk format + +Allow cryptsetup utility to activate LUKS2 devices (with appropriate +libcryptsetup) + +The change itself doesn't enforce new libcryptsetup 2.x and is backward +compatible with versions 1.x + +(cherry-picked from commit b3b4ebab02395933cde554b5a5d5c363dae3920d) + +Resolves: #1573838 +--- + src/cryptsetup/cryptsetup.c | 20 ++++++++++++++------ + 1 file changed, 14 insertions(+), 6 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c +index 69a015614..528c36c48 100644 +--- a/src/cryptsetup/cryptsetup.c ++++ b/src/cryptsetup/cryptsetup.c +@@ -36,7 +36,15 @@ + #include "libudev.h" + #include "udev-util.h" + +-static const char *arg_type = NULL; /* CRYPT_LUKS1, CRYPT_TCRYPT or CRYPT_PLAIN */ ++/* libcryptsetup define for any LUKS version, compatible with libcryptsetup 1.x */ ++#ifndef CRYPT_LUKS ++#define CRYPT_LUKS NULL ++#endif ++ ++/* internal helper */ ++#define ANY_LUKS "LUKS" ++ ++static const char *arg_type = NULL; /* ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT or CRYPT_PLAIN */ + static char *arg_cipher = NULL; + static unsigned arg_key_size = 0; + static int arg_key_slot = CRYPT_ANY_SLOT; +@@ -98,7 +106,7 @@ static int parse_one_option(const char *option) { + + } else if (startswith(option, "key-slot=")) { + +- arg_type = CRYPT_LUKS1; ++ arg_type = ANY_LUKS; + if (safe_atoi(option+9, &arg_key_slot) < 0) { + log_error("key-slot= parse failure, ignoring."); + return 0; +@@ -138,7 +146,7 @@ static int parse_one_option(const char *option) { + arg_hash = t; + + } else if (startswith(option, "header=")) { +- arg_type = CRYPT_LUKS1; ++ arg_type = ANY_LUKS; + + if (!path_is_absolute(option+7)) { + log_error("Header path '%s' is not absolute, refusing.", option+7); +@@ -168,7 +176,7 @@ static int parse_one_option(const char *option) { + else if (STR_IN_SET(option, "allow-discards", "discard")) + arg_discards = true; + else if (streq(option, "luks")) +- arg_type = CRYPT_LUKS1; ++ arg_type = ANY_LUKS; + else if (streq(option, "tcrypt")) + arg_type = CRYPT_TCRYPT; + else if (streq(option, "tcrypt-hidden")) { +@@ -430,8 +438,8 @@ static int attach_luks_or_plain(struct crypt_device *cd, + assert(name); + assert(key_file || passwords); + +- if (!arg_type || streq(arg_type, CRYPT_LUKS1)) { +- r = crypt_load(cd, CRYPT_LUKS1, NULL); ++ if (!arg_type || STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1)) { ++ r = crypt_load(cd, CRYPT_LUKS, NULL); + if (r < 0) { + log_error("crypt_load() failed on device %s.\n", crypt_get_device_name(cd)); + return r; diff --git a/SOURCES/0624-core-scope-fix-missing-fragment_path.patch b/SOURCES/0624-core-scope-fix-missing-fragment_path.patch new file mode 100644 index 00000000..43fd5789 --- /dev/null +++ b/SOURCES/0624-core-scope-fix-missing-fragment_path.patch @@ -0,0 +1,56 @@ +From f838bf376249b68205641d1736da2622c0279ed2 Mon Sep 17 00:00:00 2001 +From: chenglin130 +Date: Sat, 20 Jan 2018 17:45:27 +0800 +Subject: [PATCH] core:scope: fix missing fragment_path + +fragment_path in struct unit is a record of unit file, which will +be deleted (unlink) in unit_free(). + +After a daemon-reload process, the u->fragment_path of scope unit +will be missing (NULL). Then, the discarded session scope unit file +will be redundant until reboot. + +Steps to Reproduce problem: +1. ssh access and login +2. systemctl daemon-reload +3. ssh logout +4. discarded session-xxx.scope file will be found in /run/systemd/system/ + +So in a daemon-reload case, scope_load() need unit_load_fragment() to reload +u->fragment_path. +--- + src/core/load-fragment.c | 5 +++++ + src/core/scope.c | 4 ++++ + 2 files changed, 9 insertions(+) + +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index da58bcc5c..f3d0851fe 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -3950,6 +3950,11 @@ int unit_load_fragment(Unit *u) { + assert(u->load_state == UNIT_STUB); + assert(u->id); + ++ if (u->transient && u->fragment_path) { ++ u->load_state = UNIT_LOADED; ++ return 0; ++ } ++ + /* First, try to find the unit under its id. We always look + * for unit files in the default directories, to make it easy + * to override things by placing things in /etc/systemd/system */ +diff --git a/src/core/scope.c b/src/core/scope.c +index ae6614fbf..29954ba28 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -150,6 +150,10 @@ static int scope_load(Unit *u) { + if (!u->transient && UNIT(s)->manager->n_reloading <= 0) + return -ENOENT; + ++ r = unit_load_fragment(u); ++ if (r < 0) ++ return r; ++ + u->load_state = UNIT_LOADED; + + r = unit_load_dropin(u); diff --git a/SOURCES/0625-units-don-t-put-udev-to-its-own-mount-namespace-with.patch b/SOURCES/0625-units-don-t-put-udev-to-its-own-mount-namespace-with.patch new file mode 100644 index 00000000..8a4703c8 --- /dev/null +++ b/SOURCES/0625-units-don-t-put-udev-to-its-own-mount-namespace-with.patch @@ -0,0 +1,27 @@ +From 5c62e7afe2197c7b5bb00ed70bc6960b49a0317e Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 18 Jan 2018 19:23:56 +0100 +Subject: [PATCH] units: don't put udev to its own mount namespace with slave + propagation + +Change in upstream was done mostly for political reasons to discourage +people from doing mounts in udev rules. RHEL is very bad place for +such experiments. Revert to default we shipped with RHEL-7 GA. + +RHEL-only + +Resolves: #1432211 +--- + units/systemd-udevd.service.in | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in +index 32f04d901..46b079515 100644 +--- a/units/systemd-udevd.service.in ++++ b/units/systemd-udevd.service.in +@@ -21,5 +21,4 @@ Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket + Restart=always + RestartSec=0 + ExecStart=@rootlibexecdir@/systemd-udevd +-MountFlags=slave + KillMode=mixed diff --git a/SOURCES/0626-rules-disable-support-for-Lenovo-IR-cameras.patch b/SOURCES/0626-rules-disable-support-for-Lenovo-IR-cameras.patch new file mode 100644 index 00000000..ffdd7e35 --- /dev/null +++ b/SOURCES/0626-rules-disable-support-for-Lenovo-IR-cameras.patch @@ -0,0 +1,37 @@ +From 647615bfa4015336eb88f6cb44dc111f1d713df7 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 13 Jun 2018 14:33:18 +0200 +Subject: [PATCH] rules: disable support for Lenovo IR cameras + +Resolves: #1540418 +--- + Makefile.am | 1 + + rules/40-redhat-disable-lenovo-ir-camera.rules | 6 ++++++ + 2 files changed, 7 insertions(+) + create mode 100644 rules/40-redhat-disable-lenovo-ir-camera.rules + +diff --git a/Makefile.am b/Makefile.am +index 8c73326fa..cbc120dad 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3522,6 +3522,7 @@ dist_udevrules_DATA += \ + rules/80-net-setup-link.rules \ + rules/95-udev-late.rules \ + rules/40-redhat.rules \ ++ rules/40-redhat-disable-lenovo-ir-camera.rules \ + rules/73-idrac.rules \ + rules/80-net-name-slot.rules + +diff --git a/rules/40-redhat-disable-lenovo-ir-camera.rules b/rules/40-redhat-disable-lenovo-ir-camera.rules +new file mode 100644 +index 000000000..ea326d4ab +--- /dev/null ++++ b/rules/40-redhat-disable-lenovo-ir-camera.rules +@@ -0,0 +1,6 @@ ++# Disable known IR cameras in Lenovo Notebooks ++SUBSYSTEM=="usb", ATTRS{idVendor}=="5986", ATTRS{idProduct}=="211a", ATTR{authorized}="0" ++SUBSYSTEM=="usb", ATTRS{idVendor}=="5986", ATTRS{idProduct}=="1141", ATTR{authorized}="0" ++SUBSYSTEM=="usb", ATTRS{idVendor}=="04f2", ATTRS{idProduct}=="b605", ATTR{authorized}="0" ++SUBSYSTEM=="usb", ATTRS{idVendor}=="04f2", ATTRS{idProduct}=="b613", ATTR{authorized}="0" ++SUBSYSTEM=="usb", ATTRS{idVendor}=="04f2", ATTRS{idProduct}=="b615", ATTR{authorized}="0" +\ No newline at end of file diff --git a/SOURCES/0627-core-make-sure-systemctl-reload-or-try-restart-is-ac.patch b/SOURCES/0627-core-make-sure-systemctl-reload-or-try-restart-is-ac.patch new file mode 100644 index 00000000..ad3a14ed --- /dev/null +++ b/SOURCES/0627-core-make-sure-systemctl-reload-or-try-restart-is-ac.patch @@ -0,0 +1,92 @@ +From f7507f4bb5385ed0303451d812d220f14f341629 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Thu, 28 Jan 2016 18:48:42 +0100 +Subject: [PATCH] core: make sure "systemctl reload-or-try-restart is actually + a noop if a unit is not running + +This makes sure we follow the same basic logic for try-restart if we have a try-reload. + +Fixes #688 + +(cherry picked from commit 3282591dc30b2934a895c7403d2f0b0690260947) +Resolves: #1191920 +--- + src/core/dbus-unit.c | 2 +- + src/core/job.c | 8 ++++++++ + src/core/job.h | 3 +++ + src/core/unit.c | 2 ++ + 4 files changed, 14 insertions(+), 1 deletion(-) + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index 1d0d6f67c..f0f75e01b 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -850,7 +850,7 @@ int bus_unit_queue_job( + if (type == JOB_RESTART) + type = JOB_RELOAD_OR_START; + else if (type == JOB_TRY_RESTART) +- type = JOB_RELOAD; ++ type = JOB_TRY_RELOAD; + } + + r = mac_selinux_unit_access_check( +diff --git a/src/core/job.c b/src/core/job.c +index 1617e24c0..c9a43a4cb 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -404,6 +404,13 @@ JobType job_type_collapse(JobType t, Unit *u) { + + return JOB_RESTART; + ++ case JOB_TRY_RELOAD: ++ s = unit_active_state(u); ++ if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) ++ return JOB_NOP; ++ ++ return JOB_RELOAD; ++ + case JOB_RELOAD_OR_START: + s = unit_active_state(u); + if (UNIT_IS_INACTIVE_OR_DEACTIVATING(s)) +@@ -1212,6 +1219,7 @@ static const char* const job_type_table[_JOB_TYPE_MAX] = { + [JOB_RELOAD_OR_START] = "reload-or-start", + [JOB_RESTART] = "restart", + [JOB_TRY_RESTART] = "try-restart", ++ [JOB_TRY_RELOAD] = "try-reload", + [JOB_NOP] = "nop", + }; + +diff --git a/src/core/job.h b/src/core/job.h +index ce81607de..535052b48 100644 +--- a/src/core/job.h ++++ b/src/core/job.h +@@ -63,6 +63,9 @@ enum JobType { + * Thus we never need to merge it with anything. */ + JOB_TRY_RESTART = _JOB_TYPE_MAX_IN_TRANSACTION, /* if running, stop and then start */ + ++ /* Similar to JOB_TRY_RESTART but collapses to JOB_RELOAD or JOB_NOP */ ++ JOB_TRY_RELOAD, ++ + /* JOB_RELOAD_OR_START won't enter into a transaction and cannot result + * from transaction merging (there's no way for JOB_RELOAD and + * JOB_START to meet in one transaction). It can result from a merge +diff --git a/src/core/unit.c b/src/core/unit.c +index 41d7b63d7..6d535ae12 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1868,6 +1868,7 @@ void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, bool reload_su + + case JOB_RELOAD: + case JOB_RELOAD_OR_START: ++ case JOB_TRY_RELOAD: + + if (u->job->state == JOB_RUNNING) { + if (ns == UNIT_ACTIVE) +@@ -2144,6 +2145,7 @@ bool unit_job_is_applicable(Unit *u, JobType j) { + return unit_can_start(u); + + case JOB_RELOAD: ++ case JOB_TRY_RELOAD: + return unit_can_reload(u); + + case JOB_RELOAD_OR_START: diff --git a/SOURCES/0628-core-fix-confusing-logging-of-instantaneous-jobs.patch b/SOURCES/0628-core-fix-confusing-logging-of-instantaneous-jobs.patch new file mode 100644 index 00000000..30a8a3c9 --- /dev/null +++ b/SOURCES/0628-core-fix-confusing-logging-of-instantaneous-jobs.patch @@ -0,0 +1,247 @@ +From 7bc07eb6c9a31f2c26d0fe3e6d7a26a13cbb2369 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 16 Jul 2015 20:08:30 +0200 +Subject: [PATCH] core: fix confusing logging of instantaneous jobs + +For instantaneous jobs (e.g. starting of targets, sockets, slices, or +Type=simple services) the log shows the job completion +before starting: + + systemd[1]: Created slice -.slice. + systemd[1]: Starting -.slice. + systemd[1]: Created slice System Slice. + systemd[1]: Starting System Slice. + systemd[1]: Listening on Journal Audit Socket. + systemd[1]: Starting Journal Audit Socket. + systemd[1]: Reached target Timers. + systemd[1]: Starting Timers. + ... + +The reason is that the job completes before the ->start() method returns +and only then does unit_start() print the "Starting ..." message. +The same thing happens when stopping units. + +Rather than fixing the order of the messages, let's just not emit the +Starting/Stopping message at all when the job completes instantaneously. +The job completion message is sufficient in this case. + +(cherry picked from commit d1a34ae9c20f1c02aab17884919eccef572b1d21) + +Resolves: #1506256 +--- + src/core/job.c | 65 +++++++++++++++++++++++++++++++++++++++------------------ + src/core/unit.c | 36 +++++++++++--------------------- + src/core/unit.h | 1 + + 3 files changed, 58 insertions(+), 44 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index c9a43a4cb..612caa604 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -504,10 +504,48 @@ static void job_change_type(Job *j, JobType newtype) { + j->type = newtype; + } + ++static int job_perform_on_unit(Job **j) { ++ /* While we execute this operation the job might go away (for ++ * example: because it finishes immediately or is replaced by a new, ++ * conflicting job.) To make sure we don't access a freed job later on ++ * we store the id here, so that we can verify the job is still ++ * valid. */ ++ Manager *m = (*j)->manager; ++ Unit *u = (*j)->unit; ++ JobType t = (*j)->type; ++ uint32_t id = (*j)->id; ++ int r; ++ ++ switch (t) { ++ case JOB_START: ++ r = unit_start(u); ++ break; ++ ++ case JOB_RESTART: ++ t = JOB_STOP; ++ case JOB_STOP: ++ r = unit_stop(u); ++ break; ++ ++ case JOB_RELOAD: ++ r = unit_reload(u); ++ break; ++ ++ default: ++ assert_not_reached("Invalid job type"); ++ } ++ ++ /* Log if the job still exists and the start/stop/reload function ++ * actually did something. */ ++ *j = manager_get_job(m, id); ++ if (*j && r > 0) ++ unit_status_emit_starting_stopping_reloading(u, t); ++ ++ return r; ++} ++ + int job_run_and_invalidate(Job *j) { + int r; +- uint32_t id; +- Manager *m = j->manager; + + assert(j); + assert(j->installed); +@@ -526,23 +564,9 @@ int job_run_and_invalidate(Job *j) { + job_set_state(j, JOB_RUNNING); + job_add_to_dbus_queue(j); + +- /* While we execute this operation the job might go away (for +- * example: because it is replaced by a new, conflicting +- * job.) To make sure we don't access a freed job later on we +- * store the id here, so that we can verify the job is still +- * valid. */ +- id = j->id; + + switch (j->type) { + +- case JOB_START: +- r = unit_start(j->unit); +- +- /* If this unit cannot be started, then simply wait */ +- if (r == -EBADR) +- r = 0; +- break; +- + case JOB_VERIFY_ACTIVE: { + UnitActiveState t = unit_active_state(j->unit); + if (UNIT_IS_ACTIVE_OR_RELOADING(t)) +@@ -554,17 +578,19 @@ int job_run_and_invalidate(Job *j) { + break; + } + ++ case JOB_START: + case JOB_STOP: + case JOB_RESTART: +- r = unit_stop(j->unit); ++ r = job_perform_on_unit(&j); + +- /* If this unit cannot stopped, then simply wait. */ ++ /* If the unit type does not support starting/stopping, ++ * then simply wait. */ + if (r == -EBADR) + r = 0; + break; + + case JOB_RELOAD: +- r = unit_reload(j->unit); ++ r = job_perform_on_unit(&j); + break; + + case JOB_NOP: +@@ -575,7 +601,6 @@ int job_run_and_invalidate(Job *j) { + assert_not_reached("Unknown job type"); + } + +- j = manager_get_job(m, id); + if (j) { + if (r == -EALREADY) + r = job_finish_and_invalidate(j, JOB_DONE, true, true); +diff --git a/src/core/unit.c b/src/core/unit.c +index 6d535ae12..907a4bf7f 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1417,6 +1417,15 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { + NULL); + } + ++void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t) { ++ ++ unit_status_log_starting_stopping_reloading(u, t); ++ ++ /* Reload status messages have traditionally not been printed to console. */ ++ if (t != JOB_RELOAD) ++ unit_status_print_starting_stopping(u, t); ++} ++ + /* Errors: + * -EBADR: This unit type does not support starting. + * -EALREADY: Unit is already started. +@@ -1427,7 +1436,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { + int unit_start(Unit *u) { + UnitActiveState state; + Unit *following; +- int r; + + assert(u); + +@@ -1481,14 +1489,7 @@ int unit_start(Unit *u) { + + unit_add_to_dbus_queue(u); + +- r = UNIT_VTABLE(u)->start(u); +- if (r <= 0) +- return r; +- +- /* Log if the start function actually did something */ +- unit_status_log_starting_stopping_reloading(u, JOB_START); +- unit_status_print_starting_stopping(u, JOB_START); +- return r; ++ return UNIT_VTABLE(u)->start(u); + } + + bool unit_can_start(Unit *u) { +@@ -1512,7 +1513,6 @@ bool unit_can_isolate(Unit *u) { + int unit_stop(Unit *u) { + UnitActiveState state; + Unit *following; +- int r; + + assert(u); + +@@ -1531,13 +1531,7 @@ int unit_stop(Unit *u) { + + unit_add_to_dbus_queue(u); + +- r = UNIT_VTABLE(u)->stop(u); +- if (r <= 0) +- return r; +- +- unit_status_log_starting_stopping_reloading(u, JOB_STOP); +- unit_status_print_starting_stopping(u, JOB_STOP); +- return r; ++ return UNIT_VTABLE(u)->stop(u); + } + + /* Errors: +@@ -1548,7 +1542,6 @@ int unit_stop(Unit *u) { + int unit_reload(Unit *u) { + UnitActiveState state; + Unit *following; +- int r; + + assert(u); + +@@ -1575,12 +1568,7 @@ int unit_reload(Unit *u) { + + unit_add_to_dbus_queue(u); + +- r = UNIT_VTABLE(u)->reload(u); +- if (r <= 0) +- return r; +- +- unit_status_log_starting_stopping_reloading(u, JOB_RELOAD); +- return r; ++ return UNIT_VTABLE(u)->reload(u); + } + + bool unit_can_reload(Unit *u) { +diff --git a/src/core/unit.h b/src/core/unit.h +index 85f52df18..480e2e95f 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -562,6 +562,7 @@ int unit_add_node_link(Unit *u, const char *what, bool wants, UnitDependency d); + int unit_coldplug(Unit *u, Hashmap *deferred_work); + + void unit_status_printf(Unit *u, const char *status, const char *unit_status_msg_format) _printf_(3, 0); ++void unit_status_emit_starting_stopping_reloading(Unit *u, JobType t); + + bool unit_need_daemon_reload(Unit *u); + diff --git a/SOURCES/0629-core-correct-return-value-from-reload-methods.patch b/SOURCES/0629-core-correct-return-value-from-reload-methods.patch new file mode 100644 index 00000000..f140ed28 --- /dev/null +++ b/SOURCES/0629-core-correct-return-value-from-reload-methods.patch @@ -0,0 +1,43 @@ +From bc54eb811caf738ee54867359f798dc0f4be9e7e Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Thu, 16 Jul 2015 21:39:56 +0200 +Subject: [PATCH] core: correct return value from reload methods + +Return 1 from *_reload() methods to signify "we did something", just +like in *_start(). This causes "Reloading foo..." messages to be logged. +"Reloaded foo." messages are already logged. + +(cherry picked from commit 2d018ae23b838f050516d06859f50ecb9733d44b) + +Related: #1506256 +--- + src/core/mount.c | 2 +- + src/core/service.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/mount.c b/src/core/mount.c +index a6d93b869..f726d9659 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1081,7 +1081,7 @@ static int mount_reload(Unit *u) { + assert(m->state == MOUNT_MOUNTED); + + mount_enter_remounting(m); +- return 0; ++ return 1; + } + + static int mount_serialize(Unit *u, FILE *f, FDSet *fds) { +diff --git a/src/core/service.c b/src/core/service.c +index 71ec5e37c..9622ce11f 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1939,7 +1939,7 @@ static int service_reload(Unit *u) { + assert(s->state == SERVICE_RUNNING || s->state == SERVICE_EXITED); + + service_enter_reload(s); +- return 0; ++ return 1; + } + + _pure_ static bool service_can_reload(Unit *u) { diff --git a/SOURCES/0630-core-always-try-harder-to-get-unit-status-message-fo.patch b/SOURCES/0630-core-always-try-harder-to-get-unit-status-message-fo.patch new file mode 100644 index 00000000..d0579acc --- /dev/null +++ b/SOURCES/0630-core-always-try-harder-to-get-unit-status-message-fo.patch @@ -0,0 +1,91 @@ +From c571dc5f7d593a4526da9e19b35ae3d1ed11bfaa Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Mon, 20 Jul 2015 17:18:13 +0200 +Subject: [PATCH] core: always try harder to get unit status message format + string + +The starting/stopping messages are printed to the console only if the +corresponding format string is defined in the unit's vtable. To avoid +excessive messages on the console, the unit types whose start/stop +jobs are instantaneous had the format strings intentionally undefined. +When logging the same event to the journal, a fallback to generic +Starting/Stopping/Reloading messages is used. + +The problem of excessive console messages with instantaneous jobs +is already resolved in a nicer way ("core: fix confusing logging of +instantaneous jobs"), so there's no longer a need to have two ways of +getting the format strings. Let's fold them into one function with +the fallback to generic message strings. + +(cherry picked from commit a85ca902c9f7f5aa8f2f3e3299147733802cf09d) + +Related: #1506256 +--- + src/core/unit.c | 34 ++++++++++------------------------ + 1 file changed, 10 insertions(+), 24 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 907a4bf7f..a33cbdf73 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1328,32 +1328,21 @@ static bool unit_assert_test(Unit *u) { + } + + _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { +- const UnitStatusMessageFormats *format_table; +- +- assert(u); +- assert(t >= 0); +- assert(t < _JOB_TYPE_MAX); +- +- if (t != JOB_START && t != JOB_STOP) +- return NULL; +- +- format_table = &UNIT_VTABLE(u)->status_message_formats; +- if (!format_table) +- return NULL; +- +- return format_table->starting_stopping[t == JOB_STOP]; +-} +- +-_pure_ static const char *unit_get_status_message_format_try_harder(Unit *u, JobType t) { + const char *format; ++ const UnitStatusMessageFormats *format_table; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + +- format = unit_get_status_message_format(u, t); +- if (format) +- return format; ++ if (t == JOB_START || t == JOB_STOP) { ++ format_table = &UNIT_VTABLE(u)->status_message_formats; ++ if (format_table) { ++ format = format_table->starting_stopping[t == JOB_STOP]; ++ if (format) ++ return format; ++ } ++ } + + /* Return generic strings */ + if (t == JOB_START) +@@ -1371,9 +1360,6 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { + + assert(u); + +- /* We only print status messages for selected units on +- * selected operations. */ +- + format = unit_get_status_message_format(u, t); + if (!format) + return; +@@ -1398,7 +1384,7 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { + + /* We log status messages for all units and all operations. */ + +- format = unit_get_status_message_format_try_harder(u, t); ++ format = unit_get_status_message_format(u, t); + if (!format) + return; + diff --git a/SOURCES/0631-core-unit_get_status_message_format-never-returns-NU.patch b/SOURCES/0631-core-unit_get_status_message_format-never-returns-NU.patch new file mode 100644 index 00000000..a838a486 --- /dev/null +++ b/SOURCES/0631-core-unit_get_status_message_format-never-returns-NU.patch @@ -0,0 +1,63 @@ +From 0204371780cbcae7635544abc61846d33d04c317 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Mon, 20 Jul 2015 18:36:12 +0200 +Subject: [PATCH] core: unit_get_status_message_format() never returns NULL + +unit_get_status_message_format() is used only with one of JOB_START, +JOB_STOP, JOB_RELOAD, all of which have fallback message strings +defined, so the function may never return NULL. + +(cherry picked from commit b5bf308ba50ab0bac0f0caec2d8e4d5c75c107d0) + +Related: #1506256 +--- + src/core/unit.c | 13 +++---------- + 1 file changed, 3 insertions(+), 10 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index a33cbdf73..22d9beed7 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1332,10 +1332,9 @@ _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { + const UnitStatusMessageFormats *format_table; + + assert(u); +- assert(t >= 0); +- assert(t < _JOB_TYPE_MAX); ++ assert(t == JOB_START || t == JOB_STOP || t == JOB_RELOAD); + +- if (t == JOB_START || t == JOB_STOP) { ++ if (t != JOB_RELOAD) { + format_table = &UNIT_VTABLE(u)->status_message_formats; + if (format_table) { + format = format_table->starting_stopping[t == JOB_STOP]; +@@ -1349,10 +1348,8 @@ _pure_ static const char* unit_get_status_message_format(Unit *u, JobType t) { + return "Starting %s."; + else if (t == JOB_STOP) + return "Stopping %s."; +- else if (t == JOB_RELOAD) ++ else + return "Reloading %s."; +- +- return NULL; + } + + static void unit_status_print_starting_stopping(Unit *u, JobType t) { +@@ -1361,8 +1358,6 @@ static void unit_status_print_starting_stopping(Unit *u, JobType t) { + assert(u); + + format = unit_get_status_message_format(u, t); +- if (!format) +- return; + + DISABLE_WARNING_FORMAT_NONLITERAL; + unit_status_printf(u, "", format); +@@ -1385,8 +1380,6 @@ static void unit_status_log_starting_stopping_reloading(Unit *u, JobType t) { + /* We log status messages for all units and all operations. */ + + format = unit_get_status_message_format(u, t); +- if (!format) +- return; + + DISABLE_WARNING_FORMAT_NONLITERAL; + snprintf(buf, sizeof(buf), format, unit_description(u)); diff --git a/SOURCES/0632-core-try-harder-to-get-job-completion-messages-too.patch b/SOURCES/0632-core-try-harder-to-get-job-completion-messages-too.patch new file mode 100644 index 00000000..debc518a --- /dev/null +++ b/SOURCES/0632-core-try-harder-to-get-job-completion-messages-too.patch @@ -0,0 +1,254 @@ +From 50ce13182e07af7f240c61d03bf113e86a269917 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 21 Jul 2015 14:54:24 +0200 +Subject: [PATCH] core: try harder to get job completion messages too + +This is similar to "core: always try harder to get unit status +message format string", but for job completion status messages. +It makes generic status messages applicable for printing to the console. +And it rewrites the functions in a more table-based style. + +(cherry picked from commit aa49ab5f22c0fdc7a5381d4e452f40705f3d7bf8) + +Related: #1506256 +--- + src/core/job.c | 192 ++++++++++++++++++++------------------------------------- + 1 file changed, 68 insertions(+), 124 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 612caa604..f371f914d 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -622,156 +622,100 @@ int job_run_and_invalidate(Job *j) { + } + + _pure_ static const char *job_get_status_message_format(Unit *u, JobType t, JobResult result) { ++ const char *format; + const UnitStatusMessageFormats *format_table; ++ static const char *const generic_finished_start_job[_JOB_RESULT_MAX] = { ++ [JOB_DONE] = "Started %s.", ++ [JOB_TIMEOUT] = "Timed out starting %s.", ++ [JOB_FAILED] = "Failed to start %s.", ++ [JOB_DEPENDENCY] = "Dependency failed for %s.", ++ [JOB_ASSERT] = "Assertion failed for %s.", ++ [JOB_UNSUPPORTED] = "Starting of %s not supported.", ++ }; ++ static const char *const generic_finished_stop_job[_JOB_RESULT_MAX] = { ++ [JOB_DONE] = "Stopped %s.", ++ [JOB_FAILED] = "Stopped (with error) %s.", ++ [JOB_TIMEOUT] = "Timed out stoppping %s.", ++ }; ++ static const char *const generic_finished_reload_job[_JOB_RESULT_MAX] = { ++ [JOB_DONE] = "Reloaded %s.", ++ [JOB_FAILED] = "Reload failed for %s.", ++ [JOB_TIMEOUT] = "Timed out reloading %s.", ++ }; ++ /* When verify-active detects the unit is inactive, report it. ++ * Most likely a DEPEND warning from a requisiting unit will ++ * occur next and it's nice to see what was requisited. */ ++ static const char *const generic_finished_verify_active_job[_JOB_RESULT_MAX] = { ++ [JOB_SKIPPED] = "%s is not active.", ++ }; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + +- format_table = &UNIT_VTABLE(u)->status_message_formats; +- if (!format_table) +- return NULL; ++ if (t == JOB_START || t == JOB_STOP || t == JOB_RESTART) { ++ format_table = &UNIT_VTABLE(u)->status_message_formats; ++ if (format_table) { ++ format = t == JOB_START ? format_table->finished_start_job[result] : ++ format_table->finished_stop_job[result]; ++ if (format) ++ return format; ++ } ++ } + ++ /* Return generic strings */ + if (t == JOB_START) +- return format_table->finished_start_job[result]; ++ return generic_finished_start_job[result]; + else if (t == JOB_STOP || t == JOB_RESTART) +- return format_table->finished_stop_job[result]; +- +- return NULL; +-} +- +-_pure_ static const char *job_get_status_message_format_try_harder(Unit *u, JobType t, JobResult result) { +- const char *format; +- +- assert(u); +- assert(t >= 0); +- assert(t < _JOB_TYPE_MAX); +- +- format = job_get_status_message_format(u, t, result); +- if (format) +- return format; +- +- /* Return generic strings */ +- if (t == JOB_START) { +- if (result == JOB_DONE) +- return "Started %s."; +- else if (result == JOB_TIMEOUT) +- return "Timed out starting %s."; +- else if (result == JOB_FAILED) +- return "Failed to start %s."; +- else if (result == JOB_DEPENDENCY) +- return "Dependency failed for %s."; +- else if (result == JOB_ASSERT) +- return "Assertion failed for %s."; +- else if (result == JOB_UNSUPPORTED) +- return "Starting of %s not supported."; +- } else if (t == JOB_STOP || t == JOB_RESTART) { +- if (result == JOB_DONE) +- return "Stopped %s."; +- else if (result == JOB_FAILED) +- return "Stopped (with error) %s."; +- else if (result == JOB_TIMEOUT) +- return "Timed out stoppping %s."; +- } else if (t == JOB_RELOAD) { +- if (result == JOB_DONE) +- return "Reloaded %s."; +- else if (result == JOB_FAILED) +- return "Reload failed for %s."; +- else if (result == JOB_TIMEOUT) +- return "Timed out reloading %s."; +- } ++ return generic_finished_stop_job[result]; ++ else if (t == JOB_RELOAD) ++ return generic_finished_reload_job[result]; ++ else if (t == JOB_VERIFY_ACTIVE) ++ return generic_finished_verify_active_job[result]; + + return NULL; + } + + static void job_print_status_message(Unit *u, JobType t, JobResult result) { + const char *format; ++ static const char* const job_result_status_table[_JOB_RESULT_MAX] = { ++ [JOB_DONE] = ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, ++ [JOB_TIMEOUT] = ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, ++ [JOB_FAILED] = ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, ++ [JOB_DEPENDENCY] = ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, ++ [JOB_SKIPPED] = ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, ++ [JOB_ASSERT] = ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF, ++ [JOB_UNSUPPORTED] = ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF, ++ }; + + assert(u); + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + +- DISABLE_WARNING_FORMAT_NONLITERAL; +- +- if (t == JOB_START) { +- format = job_get_status_message_format(u, t, result); +- if (!format) +- return; +- +- switch (result) { +- +- case JOB_DONE: +- if (u->condition_result) +- unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format); +- break; +- +- case JOB_TIMEOUT: +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format); +- break; +- +- case JOB_FAILED: { +- _cleanup_free_ char *quoted = NULL; +- +- quoted = shell_maybe_quote(u->id); +- +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON "FAILED" ANSI_HIGHLIGHT_OFF, format); +- manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, "See 'systemctl status %s' for details.", strna(quoted)); +- break; +- } +- +- case JOB_DEPENDENCY: +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "DEPEND" ANSI_HIGHLIGHT_OFF, format); +- break; +- +- case JOB_ASSERT: +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "ASSERT" ANSI_HIGHLIGHT_OFF, format); +- break; +- +- case JOB_UNSUPPORTED: +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_YELLOW_ON "UNSUPP" ANSI_HIGHLIGHT_OFF, format); +- break; +- +- default: +- ; +- } +- +- } else if (t == JOB_STOP || t == JOB_RESTART) { +- +- format = job_get_status_message_format(u, t, result); +- if (!format) +- return; ++ /* Reload status messages have traditionally not been printed to console. */ ++ if (t == JOB_RELOAD) ++ return; + +- switch (result) { ++ if (t == JOB_START && result == JOB_DONE && !u->condition_result) ++ return; + +- case JOB_TIMEOUT: +- manager_flip_auto_status(u->manager, true); +- unit_status_printf(u, ANSI_HIGHLIGHT_RED_ON " TIME " ANSI_HIGHLIGHT_OFF, format); +- break; ++ format = job_get_status_message_format(u, t, result); ++ if (!format) ++ return; + +- case JOB_DONE: +- case JOB_FAILED: +- unit_status_printf(u, ANSI_GREEN_ON " OK " ANSI_HIGHLIGHT_OFF, format); +- break; ++ if (result != JOB_DONE) ++ manager_flip_auto_status(u->manager, true); + +- default: +- ; +- } ++ DISABLE_WARNING_FORMAT_NONLITERAL; ++ unit_status_printf(u, job_result_status_table[result], format); ++ REENABLE_WARNING; + +- } else if (t == JOB_VERIFY_ACTIVE) { ++ if (t == JOB_START && result == JOB_FAILED) { ++ _cleanup_free_ char *quoted = shell_maybe_quote(u->id); + +- /* When verify-active detects the unit is inactive, report it. +- * Most likely a DEPEND warning from a requisiting unit will +- * occur next and it's nice to see what was requisited. */ +- if (result == JOB_SKIPPED) +- unit_status_printf(u, ANSI_HIGHLIGHT_ON " INFO " ANSI_HIGHLIGHT_OFF, "%s is not active."); ++ manager_status_printf(u->manager, STATUS_TYPE_NORMAL, NULL, ++ "See 'systemctl status %s' for details.", strna(quoted)); + } +- +- REENABLE_WARNING; + } + + static void job_log_status_message(Unit *u, JobType t, JobResult result) { +@@ -788,7 +732,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + if (log_on_console()) + return; + +- format = job_get_status_message_format_try_harder(u, t, result); ++ format = job_get_status_message_format(u, t, result); + if (!format) + return; + diff --git a/SOURCES/0633-core-remove-generic-job-completion-messages-from-uni.patch b/SOURCES/0633-core-remove-generic-job-completion-messages-from-uni.patch new file mode 100644 index 00000000..64e31a3e --- /dev/null +++ b/SOURCES/0633-core-remove-generic-job-completion-messages-from-uni.patch @@ -0,0 +1,132 @@ +From 60545c63716ecc720728c221c61d575b267fbfc8 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 21 Jul 2015 15:51:16 +0200 +Subject: [PATCH] core: remove generic job completion messages from unit + vtables + +These units' message format strings are identical to the generic +strings. Since we can always rely on the fallback, these are now +redundant. + +(cherry picked from commit c382d69e3d39daedebcedb2da882beeb147a3cda) + +Related: #1506256 +--- + src/core/automount.c | 1 - + src/core/busname.c | 3 --- + src/core/mount.c | 1 - + src/core/service.c | 3 --- + src/core/slice.c | 1 - + src/core/socket.c | 1 - + src/core/swap.c | 1 - + src/core/target.c | 1 - + 8 files changed, 12 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index 679fe071e..08519e49c 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -1126,7 +1126,6 @@ const UnitVTable automount_vtable = { + .finished_start_job = { + [JOB_DONE] = "Set up automount %s.", + [JOB_FAILED] = "Failed to set up automount %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Unset automount %s.", +diff --git a/src/core/busname.c b/src/core/busname.c +index f626ba96d..a5e659049 100644 +--- a/src/core/busname.c ++++ b/src/core/busname.c +@@ -1064,13 +1064,10 @@ const UnitVTable busname_vtable = { + .finished_start_job = { + [JOB_DONE] = "Listening on %s.", + [JOB_FAILED] = "Failed to listen on %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", +- [JOB_TIMEOUT] = "Timed out starting %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Closed %s.", + [JOB_FAILED] = "Failed stopping %s.", +- [JOB_TIMEOUT] = "Timed out stopping %s.", + }, + }, + }; +diff --git a/src/core/mount.c b/src/core/mount.c +index f726d9659..0dc67dde6 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1978,7 +1978,6 @@ const UnitVTable mount_vtable = { + .finished_start_job = { + [JOB_DONE] = "Mounted %s.", + [JOB_FAILED] = "Failed to mount %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + [JOB_TIMEOUT] = "Timed out mounting %s.", + }, + .finished_stop_job = { +diff --git a/src/core/service.c b/src/core/service.c +index 9622ce11f..8303a1e7e 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -3398,13 +3398,10 @@ const UnitVTable service_vtable = { + .finished_start_job = { + [JOB_DONE] = "Started %s.", + [JOB_FAILED] = "Failed to start %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", +- [JOB_TIMEOUT] = "Timed out starting %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Stopped %s.", + [JOB_FAILED] = "Stopped (with error) %s.", +- [JOB_TIMEOUT] = "Timed out stopping %s.", + }, + }, + }; +diff --git a/src/core/slice.c b/src/core/slice.c +index 9154558b7..1cce3e121 100644 +--- a/src/core/slice.c ++++ b/src/core/slice.c +@@ -299,7 +299,6 @@ const UnitVTable slice_vtable = { + .status_message_formats = { + .finished_start_job = { + [JOB_DONE] = "Created slice %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Removed slice %s.", +diff --git a/src/core/socket.c b/src/core/socket.c +index 771af0d24..efefe7ce5 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -2736,7 +2736,6 @@ const UnitVTable socket_vtable = { + .finished_start_job = { + [JOB_DONE] = "Listening on %s.", + [JOB_FAILED] = "Failed to listen on %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + [JOB_TIMEOUT] = "Timed out starting %s.", + }, + .finished_stop_job = { +diff --git a/src/core/swap.c b/src/core/swap.c +index 984be2d9a..e71de4e65 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -1525,7 +1525,6 @@ const UnitVTable swap_vtable = { + .finished_start_job = { + [JOB_DONE] = "Activated swap %s.", + [JOB_FAILED] = "Failed to activate swap %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + [JOB_TIMEOUT] = "Timed out activating swap %s.", + }, + .finished_stop_job = { +diff --git a/src/core/target.c b/src/core/target.c +index 2411a8e75..45248ad02 100644 +--- a/src/core/target.c ++++ b/src/core/target.c +@@ -231,7 +231,6 @@ const UnitVTable target_vtable = { + .status_message_formats = { + .finished_start_job = { + [JOB_DONE] = "Reached target %s.", +- [JOB_DEPENDENCY] = "Dependency failed for %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Stopped target %s.", diff --git a/SOURCES/0634-core-do-not-log-done-failed-condition-jobs-as-if-uni.patch b/SOURCES/0634-core-do-not-log-done-failed-condition-jobs-as-if-uni.patch new file mode 100644 index 00000000..7223ea31 --- /dev/null +++ b/SOURCES/0634-core-do-not-log-done-failed-condition-jobs-as-if-uni.patch @@ -0,0 +1,67 @@ +From 0fd062edc435d9cf39022e2e92c895bf8625ad0d Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 21 Jul 2015 16:15:19 +0200 +Subject: [PATCH] core: do not log done failed-condition jobs as if unit + started + +It is misleading to see "Started foo." in the log when the unit's +condition was false. + +(cherry picked from commit 30961fa300cad21b50fe47baee523beeadb5d0bc) + +Related: #1506256 +--- + src/core/job.c | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index f371f914d..5e582b3d3 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -692,13 +692,6 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { + assert(t >= 0); + assert(t < _JOB_TYPE_MAX); + +- /* Reload status messages have traditionally not been printed to console. */ +- if (t == JOB_RELOAD) +- return; +- +- if (t == JOB_START && result == JOB_DONE && !u->condition_result) +- return; +- + format = job_get_status_message_format(u, t, result); + if (!format) + return; +@@ -768,6 +761,19 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + NULL); + } + ++static void job_emit_status_message(Unit *u, JobType t, JobResult result) { ++ ++ /* No message if the job did not actually do anything due to failed condition. */ ++ if (t == JOB_START && result == JOB_DONE && !u->condition_result) ++ return; ++ ++ job_log_status_message(u, t, result); ++ ++ /* Reload status messages have traditionally not been printed to console. */ ++ if (t != JOB_RELOAD) ++ job_print_status_message(u, t, result); ++} ++ + int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) { + Unit *u; + Unit *other; +@@ -787,10 +793,8 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr + u->id, job_type_to_string(t), job_result_to_string(result)); + + /* If this job did nothing to respective unit we don't log the status message */ +- if (!already) { +- job_print_status_message(u, t, result); +- job_log_status_message(u, t, result); +- } ++ if (!already) ++ job_emit_status_message(u, t, result); + + job_add_to_dbus_queue(j); + diff --git a/SOURCES/0635-core-log-completion-of-remaining-job-types.patch b/SOURCES/0635-core-log-completion-of-remaining-job-types.patch new file mode 100644 index 00000000..6208a2b7 --- /dev/null +++ b/SOURCES/0635-core-log-completion-of-remaining-job-types.patch @@ -0,0 +1,42 @@ +From 010b80c6215da7357114911f46742939772e18fc Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 21 Jul 2015 16:20:18 +0200 +Subject: [PATCH] core: log completion of remaining job types + +JOB_RESTART and failed JOB_VERIFY_ACTIVE completions were printed to +console but not to the log. + +(cherry picked from commit 4f29c6fea6a6c5c2c9406ad091cd6f56da21e2cb) + +Related: #1506256 +--- + src/core/job.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 5e582b3d3..086050aa7 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -743,8 +743,7 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), + NULL); +- +- } else if (t == JOB_STOP) ++ } else if (t == JOB_STOP || t == JOB_RESTART) + log_unit_struct(u->id, + result == JOB_DONE ? LOG_INFO : LOG_ERR, + LOG_MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED), +@@ -759,6 +758,12 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), + NULL); ++ else ++ log_unit_struct(u->id, ++ result == JOB_DONE ? LOG_INFO : LOG_ERR, ++ LOG_MESSAGE("%s", buf), ++ "RESULT=%s", job_result_to_string(result), ++ NULL); + } + + static void job_emit_status_message(Unit *u, JobType t, JobResult result) { diff --git a/SOURCES/0636-core-adjust-job-completion-message-log-levels.patch b/SOURCES/0636-core-adjust-job-completion-message-log-levels.patch new file mode 100644 index 00000000..2d8d5768 --- /dev/null +++ b/SOURCES/0636-core-adjust-job-completion-message-log-levels.patch @@ -0,0 +1,75 @@ +From ea366cda56dc0550b9829e4d9e733cb8b70ffb30 Mon Sep 17 00:00:00 2001 +From: Michal Schmidt +Date: Tue, 21 Jul 2015 19:07:24 +0200 +Subject: [PATCH] core: adjust job completion message log levels + +We do not print all non-OK job completion status messages to the console +in red, because not all of them are plain errors. We do however log the +same messages as LOG_ERR. + +Differentiate the log levels by deducing them from the job result in a +way that more or less matches the color of the console message. + +(cherry picked from commit 64f575d2ab9a6743d3c7172b7591c88ba243cf1b) + +Related: #1506256 +--- + src/core/job.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 086050aa7..1861c8a63 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -714,6 +714,17 @@ static void job_print_status_message(Unit *u, JobType t, JobResult result) { + static void job_log_status_message(Unit *u, JobType t, JobResult result) { + const char *format; + char buf[LINE_MAX]; ++ static const int job_result_log_level[_JOB_RESULT_MAX] = { ++ [JOB_DONE] = LOG_INFO, ++ [JOB_CANCELED] = LOG_INFO, ++ [JOB_TIMEOUT] = LOG_ERR, ++ [JOB_FAILED] = LOG_ERR, ++ [JOB_DEPENDENCY] = LOG_WARNING, ++ [JOB_SKIPPED] = LOG_NOTICE, ++ [JOB_INVALID] = LOG_INFO, ++ [JOB_ASSERT] = LOG_WARNING, ++ [JOB_UNSUPPORTED] = LOG_WARNING, ++ }; + + assert(u); + assert(t >= 0); +@@ -738,14 +749,14 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + + mid = result == JOB_DONE ? SD_MESSAGE_UNIT_STARTED : SD_MESSAGE_UNIT_FAILED; + log_unit_struct(u->id, +- result == JOB_DONE ? LOG_INFO : LOG_ERR, ++ job_result_log_level[result], + LOG_MESSAGE_ID(mid), + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), + NULL); + } else if (t == JOB_STOP || t == JOB_RESTART) + log_unit_struct(u->id, +- result == JOB_DONE ? LOG_INFO : LOG_ERR, ++ job_result_log_level[result], + LOG_MESSAGE_ID(SD_MESSAGE_UNIT_STOPPED), + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), +@@ -753,14 +764,14 @@ static void job_log_status_message(Unit *u, JobType t, JobResult result) { + + else if (t == JOB_RELOAD) + log_unit_struct(u->id, +- result == JOB_DONE ? LOG_INFO : LOG_ERR, ++ job_result_log_level[result], + LOG_MESSAGE_ID(SD_MESSAGE_UNIT_RELOADED), + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), + NULL); + else + log_unit_struct(u->id, +- result == JOB_DONE ? LOG_INFO : LOG_ERR, ++ job_result_log_level[result], + LOG_MESSAGE("%s", buf), + "RESULT=%s", job_result_to_string(result), + NULL); diff --git a/SOURCES/0637-mount-add-new-LazyUnmount-setting-for-mount-units-ma.patch b/SOURCES/0637-mount-add-new-LazyUnmount-setting-for-mount-units-ma.patch new file mode 100644 index 00000000..87b4410f --- /dev/null +++ b/SOURCES/0637-mount-add-new-LazyUnmount-setting-for-mount-units-ma.patch @@ -0,0 +1,111 @@ +From 048ed4b2fecef7003925772740bab651cb08b260 Mon Sep 17 00:00:00 2001 +From: brulon +Date: Fri, 26 Aug 2016 11:57:22 -0400 +Subject: [PATCH] mount: add new LazyUnmount= setting for mount units, mapping + to umount(8)'s "-l" switch (#3827) + +(cherry-picked commit from e520950a03419957875034bc27795b0b81d8e793) + +Resolves: #1497264 +--- + man/systemd.mount.xml | 13 +++++++++++++ + src/core/dbus-mount.c | 1 + + src/core/load-fragment-gperf.gperf.m4 | 1 + + src/core/mount.c | 8 ++++++-- + src/core/mount.h | 2 ++ + 5 files changed, 23 insertions(+), 2 deletions(-) + +diff --git a/man/systemd.mount.xml b/man/systemd.mount.xml +index dfa437b5d..1590c44ce 100644 +--- a/man/systemd.mount.xml ++++ b/man/systemd.mount.xml +@@ -329,6 +329,19 @@ + off. + + ++ ++ LazyUnmount= ++ ++ Takes a boolean argument. If true, detach the ++ filesystem from the filesystem hierarchy at time of the unmount ++ operation, and clean up all references to the filesystem as ++ soon as they are not busy anymore. ++ This corresponds with ++ umount8's ++ -l switch. Defaults to ++ off. ++ ++ + + DirectoryMode= + Directories of mount points (and any parent +diff --git a/src/core/dbus-mount.c b/src/core/dbus-mount.c +index 04beba631..cbb842f70 100644 +--- a/src/core/dbus-mount.c ++++ b/src/core/dbus-mount.c +@@ -110,6 +110,7 @@ const sd_bus_vtable bus_mount_vtable[] = { + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Mount, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("DirectoryMode", "u", bus_property_get_mode, offsetof(Mount, directory_mode), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("SloppyOptions", "b", bus_property_get_bool, offsetof(Mount, sloppy_options), SD_BUS_VTABLE_PROPERTY_CONST), ++ SD_BUS_PROPERTY("LazyUnmount", "b", bus_property_get_bool, offsetof(Mount, lazy_unmount), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Mount, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_VTABLE("ExecMount", offsetof(Mount, exec_command[MOUNT_EXEC_MOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), + BUS_EXEC_COMMAND_VTABLE("ExecUnmount", offsetof(Mount, exec_command[MOUNT_EXEC_UNMOUNT]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION), +diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 +index b2fe627af..664bba0ef 100644 +--- a/src/core/load-fragment-gperf.gperf.m4 ++++ b/src/core/load-fragment-gperf.gperf.m4 +@@ -316,6 +316,7 @@ Mount.Type, config_parse_string, 0, + Mount.TimeoutSec, config_parse_sec, 0, offsetof(Mount, timeout_usec) + Mount.DirectoryMode, config_parse_mode, 0, offsetof(Mount, directory_mode) + Mount.SloppyOptions, config_parse_bool, 0, offsetof(Mount, sloppy_options) ++Mount.LazyUnmount, config_parse_bool, 0, offsetof(Mount, lazy_unmount) + EXEC_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl + CGROUP_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl + KILL_CONTEXT_CONFIG_ITEMS(Mount)m4_dnl +diff --git a/src/core/mount.c b/src/core/mount.c +index 0dc67dde6..5fd7a86dd 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -690,7 +690,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { + "%sOptions: %s\n" + "%sFrom /proc/self/mountinfo: %s\n" + "%sFrom fragment: %s\n" +- "%sDirectoryMode: %04o\n", ++ "%sDirectoryMode: %04o\n" ++ "%sLazyUnmount: %s\n", + prefix, mount_state_to_string(m->state), + prefix, mount_result_to_string(m->result), + prefix, m->where, +@@ -699,7 +700,8 @@ static void mount_dump(Unit *u, FILE *f, const char *prefix) { + prefix, p ? strna(p->options) : "n/a", + prefix, yes_no(m->from_proc_self_mountinfo), + prefix, yes_no(m->from_fragment), +- prefix, m->directory_mode); ++ prefix, m->directory_mode, ++ prefix, yes_no(m->lazy_unmount)); + + if (m->control_pid > 0) + fprintf(f, +@@ -891,6 +893,8 @@ static void mount_enter_unmounting(Mount *m) { + m->control_command = m->exec_command + MOUNT_EXEC_UNMOUNT; + + r = exec_command_set(m->control_command, "/bin/umount", m->where, NULL); ++ if (r >= 0 && m->lazy_unmount) ++ r = exec_command_append(m->control_command, "-l", NULL); + if (r < 0) + goto fail; + +diff --git a/src/core/mount.h b/src/core/mount.h +index 353222000..4e870299c 100644 +--- a/src/core/mount.h ++++ b/src/core/mount.h +@@ -90,6 +90,8 @@ struct Mount { + + bool sloppy_options; + ++ bool lazy_unmount; ++ + MountResult result; + MountResult reload_result; + diff --git a/SOURCES/0638-rules-Add-MODEL_ID-for-NVMe-device-7037.patch b/SOURCES/0638-rules-Add-MODEL_ID-for-NVMe-device-7037.patch new file mode 100644 index 00000000..7d742c76 --- /dev/null +++ b/SOURCES/0638-rules-Add-MODEL_ID-for-NVMe-device-7037.patch @@ -0,0 +1,42 @@ +From 14ca846073e3b7accb71012a9612d0a7cb6b5ea6 Mon Sep 17 00:00:00 2001 +From: gwendalcr +Date: Wed, 20 Jun 2018 16:54:05 +0200 +Subject: [PATCH] rules: Add MODEL_ID for NVMe device (#7037) + +To mimic MODEL_ID variable built for ATA and SCSI devices, add rules +to add MODEL_ID variable for NVMe devices. + +TEST: Check on a system with NVMe device that MODEL_ID variable is +present: + udevadm info --query=all -n /dev/nvme0n1p1 | grep ID_MODEL +and + udevadm info --query=all -n /dev/nvme0n1p1 | grep ID_MODEL +return: +E: ID_MODEL=SAMSUNG... + +(cherry picked from commit e2c2d70ba7cc7497b03c4a377bfb529035540aa7) + +Resolves: #1397264 +--- + rules/60-persistent-storage.rules | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules +index ba619633b..4aae97a9f 100644 +--- a/rules/60-persistent-storage.rules ++++ b/rules/60-persistent-storage.rules +@@ -28,10 +28,12 @@ KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{wwid}=="?*" + + KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" + KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{wwid}=="?*", ENV{ID_WWN}="$attr{wwid}" +-KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}", OPTIONS="string_escape=replace" ++KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" ++KERNEL=="nvme*[0-9]n*[0-9]", ENV{DEVTYPE}=="disk", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}", OPTIONS="string_escape=replace" + + KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{serial}=="?*", ENV{ID_SERIAL_SHORT}="$attr{serial}" +-KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$attr{model}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n", OPTIONS="string_escape=replace" ++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ATTRS{model}=="?*", ENV{ID_MODEL}="$attr{model}" ++KERNEL=="nvme*[0-9]n*[0-9]p*[0-9]", ENV{DEVTYPE}=="partition", ENV{ID_MODEL}=="?*", ENV{ID_SERIAL_SHORT}=="?*", ENV{ID_SERIAL}="$env{ID_MODEL}_$env{ID_SERIAL_SHORT}", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n", OPTIONS="string_escape=replace" + + # virtio-blk + KERNEL=="vd*[!0-9]", ATTRS{serial}=="?*", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/virtio-$env{ID_SERIAL}" diff --git a/SOURCES/0639-umount-always-use-MNT_FORCE-in-umount_all-7213.patch b/SOURCES/0639-umount-always-use-MNT_FORCE-in-umount_all-7213.patch new file mode 100644 index 00000000..95946ca5 --- /dev/null +++ b/SOURCES/0639-umount-always-use-MNT_FORCE-in-umount_all-7213.patch @@ -0,0 +1,72 @@ +From 5bace483dedc9098da8191f39c823649948a7a3c Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Wed, 8 Nov 2017 19:29:32 +1100 +Subject: [PATCH] umount: always use MNT_FORCE in umount_all() (#7213) + +The linux umount2() systemcall accepts a MNT_FORCE flags +which some filesystems honor, particularly FUSE and various +network filesystems such as NFS. +These filesystems can sometimes wait for an indefinite period +for a response from an external service, and the wait if +sometimes "uninterruptible" meaning that the process cannot be +killed. +Using MNT_FORCE causes any such request that are outstanding to +be aborted. This normally allows the waiting process to +be killed. It will then realease and reference it has to the +filesytem, this allowing the filesystem to be unmounted. + +If there remain active references to the filesystem, MNT_FORCE +is *not* forcefull enough to unmount the filesystem anyway. + +By the time that umount_all() is run by systemd-shutdown, all +filesystems *should* be unmounted, and sync() will have been +called. Anything that remains cannot be unmounted in a +completely clean manner and just nees to be dealt with as firmly +as possible. So use MNT_FORCE and try to explain why in the +comment. + +Also enhance an earlier comment to explain why umount2() is +safe even though mount(MNT_REMOUNT) isn't. + +(cherry picked from commit c44cac7c6c43407d28bd8daebff39f6145a2a33e) + +Resolves: #1571098 +--- + src/core/umount.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/src/core/umount.c b/src/core/umount.c +index 3eec0d459..91d67c06c 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -377,7 +377,9 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e + the superblock here, not the bind mount. + If the filesystem is a network fs, also skip the + remount. It brings no value (we cannot leave +- a "dirty fs") and could hang if the network is down. */ ++ a "dirty fs") and could hang if the network is down. ++ Note that umount2() is more careful and will not ++ hang because of the network being down. */ + if (detect_container(NULL) <= 0 && + !fstype_is_network(m->type)) { + _cleanup_free_ char *options = NULL; +@@ -418,11 +420,15 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e + ) + continue; + +- /* Trying to umount. We don't force here since we rely +- * on busy NFS and FUSE file systems to return EBUSY +- * until we closed everything on top of them. */ ++ /* Trying to umount. Using MNT_FORCE causes some ++ * filesystems (e.g. FUSE and NFS and other network ++ * filesystems) to abort any pending requests and ++ * return -EIO rather than blocking indefinitely. ++ * If the filesysten is "busy", this may allow processes ++ * to die, thus making the filesystem less busy so ++ * the unmount might succeed (rather then return EBUSY).*/ + log_info("Unmounting %s.", m->path); +- if (umount2(m->path, 0) == 0) { ++ if (umount2(m->path, MNT_FORCE) == 0) { + if (changed) + *changed = true; + diff --git a/SOURCES/0640-core-Implement-timeout-based-umount-remount-limit.patch b/SOURCES/0640-core-Implement-timeout-based-umount-remount-limit.patch new file mode 100644 index 00000000..a2be213b --- /dev/null +++ b/SOURCES/0640-core-Implement-timeout-based-umount-remount-limit.patch @@ -0,0 +1,305 @@ +From 5ccae46f2a192a9347feb604901127c55ce1e039 Mon Sep 17 00:00:00 2001 +From: Kyle Walker +Date: Wed, 13 Dec 2017 12:49:26 -0500 +Subject: [PATCH] core: Implement timeout based umount/remount limit + +Remount, and subsequent umount, attempts can hang for inaccessible network +based mount points. This can leave a system in a hard hang state that +requires a hard reset in order to recover. This change moves the remount, +and umount attempts into separate child processes. The remount and umount +operations will block for up to 90 seconds (DEFAULT_TIMEOUT_USEC). Should +those waits fail, the parent will issue a SIGKILL to the child and continue +with the shutdown efforts. + +In addition, instead of only reporting some additional errors on the final +attempt, failures are reported as they occur. + +(cherry picked from commit d5641e0d7e8f55937fbc3a7ecd667e42c5836d80) + +Related: #1571098 +--- + src/core/umount.c | 112 +++++++++++++++++++++++++++++++++++++--------- + src/shared/def.h | 2 - + src/shared/login-shared.c | 1 + + src/shared/util.c | 61 +++++++++++++++++++++++++ + src/shared/util.h | 16 +++++++ + 5 files changed, 168 insertions(+), 24 deletions(-) + +diff --git a/src/core/umount.c b/src/core/umount.c +index 91d67c06c..bd3896612 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -363,7 +363,84 @@ static int delete_dm(dev_t devnum) { + return r >= 0 ? 0 : -errno; + } + +-static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_error) { ++static int remount_with_timeout(MountPoint *m, char *options, int *n_failed) { ++ pid_t pid; ++ int r; ++ ++ BLOCK_SIGNALS(SIGCHLD); ++ ++ /* Due to the possiblity of a remount operation hanging, we ++ * fork a child process and set a timeout. If the timeout ++ * lapses, the assumption is that that particular remount ++ * failed. */ ++ pid = fork(); ++ if (pid < 0) ++ return log_error_errno(errno, "Failed to fork: %m"); ++ ++ if (pid == 0) { ++ log_info("Remounting '%s' read-only in with options '%s'.", m->path, options); ++ ++ /* Start the mount operation here in the child */ ++ r = mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options); ++ if (r < 0) ++ log_error_errno(errno, "Failed to remount '%s' read-only: %m", m->path); ++ ++ _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); ++ } ++ ++ r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC); ++ if (r == -ETIMEDOUT) { ++ log_error_errno(errno, "Remounting '%s' - timed out, issuing SIGKILL to PID "PID_FMT".", m->path, pid); ++ (void) kill(pid, SIGKILL); ++ } else if (r < 0) ++ log_error_errno(r, "Failed to wait for process: %m"); ++ ++ return r; ++} ++ ++static int umount_with_timeout(MountPoint *m, bool *changed) { ++ pid_t pid; ++ int r; ++ ++ BLOCK_SIGNALS(SIGCHLD); ++ ++ /* Due to the possiblity of a umount operation hanging, we ++ * fork a child process and set a timeout. If the timeout ++ * lapses, the assumption is that that particular umount ++ * failed. */ ++ pid = fork(); ++ if (pid < 0) ++ return log_error_errno(errno, "Failed to fork: %m"); ++ ++ if (pid == 0) { ++ log_info("Unmounting '%s'.", m->path); ++ ++ /* Start the mount operation here in the child Using MNT_FORCE ++ * causes some filesystems (e.g. FUSE and NFS and other network ++ * filesystems) to abort any pending requests and return -EIO ++ * rather than blocking indefinitely. If the filesysten is ++ * "busy", this may allow processes to die, thus making the ++ * filesystem less busy so the unmount might succeed (rather ++ * then return EBUSY).*/ ++ r = umount2(m->path, MNT_FORCE); ++ if (r < 0) ++ log_error_errno(errno, "Failed to unmount %s: %m", m->path); ++ ++ _exit(r < 0 ? EXIT_FAILURE : EXIT_SUCCESS); ++ } ++ ++ r = wait_for_terminate_with_timeout(pid, DEFAULT_TIMEOUT_USEC); ++ if (r == -ETIMEDOUT) { ++ log_error_errno(errno, "Unmounting '%s' - timed out, issuing SIGKILL to PID "PID_FMT".", m->path, pid); ++ (void) kill(pid, SIGKILL); ++ } else if (r < 0) ++ log_error_errno(r, "Failed to wait for process: %m"); ++ ++ return r; ++} ++ ++ ++static int mount_points_list_umount(MountPoint **head, bool *changed) { + MountPoint *m, *n; + int n_failed = 0; + +@@ -405,9 +482,13 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e + * explicitly remount the super block of that + * alias read-only we hence should be + * relatively safe regarding keeping the fs we +- * can otherwise not see dirty. */ +- log_info("Remounting '%s' read-only with options '%s'.", m->path, options); +- (void) mount(NULL, m->path, NULL, MS_REMOUNT|MS_RDONLY, options); ++ * can otherwise not see dirty. ++ * ++ * Since the remount can hang in the instance of ++ * remote filesystems, we remount asynchronously ++ * and skip the subsequent umount if it fails */ ++ if (remount_with_timeout(m, options, &n_failed) < 0) ++ continue; + } + + /* Skip / and /usr since we cannot unmount that +@@ -420,22 +501,14 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e + ) + continue; + +- /* Trying to umount. Using MNT_FORCE causes some +- * filesystems (e.g. FUSE and NFS and other network +- * filesystems) to abort any pending requests and +- * return -EIO rather than blocking indefinitely. +- * If the filesysten is "busy", this may allow processes +- * to die, thus making the filesystem less busy so +- * the unmount might succeed (rather then return EBUSY).*/ +- log_info("Unmounting %s.", m->path); +- if (umount2(m->path, MNT_FORCE) == 0) { ++ /* Trying to umount */ ++ if (umount_with_timeout(m, changed) < 0) ++ n_failed++; ++ else { + if (changed) + *changed = true; + + mount_point_free(head, m); +- } else if (log_error) { +- log_warning_errno(errno, "Could not unmount %s: %m", m->path); +- n_failed++; + } + } + +@@ -550,17 +623,12 @@ int umount_all(bool *changed) { + do { + umount_changed = false; + +- mount_points_list_umount(&mp_list_head, &umount_changed, false); ++ mount_points_list_umount(&mp_list_head, &umount_changed); + if (umount_changed) + *changed = true; + + } while (umount_changed); + +- /* umount one more time with logging enabled */ +- r = mount_points_list_umount(&mp_list_head, &umount_changed, true); +- if (r <= 0) +- goto end; +- + end: + mount_points_list_free(&mp_list_head); + +diff --git a/src/shared/def.h b/src/shared/def.h +index 9e008a6d2..f193ab1f9 100644 +--- a/src/shared/def.h ++++ b/src/shared/def.h +@@ -21,8 +21,6 @@ + along with systemd; If not, see . + ***/ + +-#include "util.h" +- + #define DEFAULT_TIMEOUT_USEC (90*USEC_PER_SEC) + #define DEFAULT_RESTART_USEC (100*USEC_PER_MSEC) + #define DEFAULT_CONFIRM_USEC (30*USEC_PER_SEC) +diff --git a/src/shared/login-shared.c b/src/shared/login-shared.c +index 054c77503..5da0f0583 100644 +--- a/src/shared/login-shared.c ++++ b/src/shared/login-shared.c +@@ -21,6 +21,7 @@ + + #include "login-shared.h" + #include "def.h" ++#include "util.h" + + bool session_id_valid(const char *id) { + assert(id); +diff --git a/src/shared/util.c b/src/shared/util.c +index 982f5e044..3216f004a 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -9049,3 +9049,64 @@ try_dev_shm_without_o_tmpfile: + + return -EOPNOTSUPP; + } ++ ++/* ++ * Return values: ++ * < 0 : wait_for_terminate_with_timeout() failed to get the state of the ++ * process, the process timed out, the process was terminated by a ++ * signal, or failed for an unknown reason. ++ * >=0 : The process terminated normally with no failures. ++ * ++ * Success is indicated by a return value of zero, a timeout is indicated ++ * by ETIMEDOUT, and all other child failure states are indicated by error ++ * is indicated by a non-zero value. ++*/ ++int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout) { ++ sigset_t mask; ++ int r; ++ usec_t until; ++ ++ assert_se(sigemptyset(&mask) == 0); ++ assert_se(sigaddset(&mask, SIGCHLD) == 0); ++ ++ /* Drop into a sigtimewait-based timeout. Waiting for the ++ * pid to exit. */ ++ until = now(CLOCK_MONOTONIC) + timeout; ++ for (;;) { ++ usec_t n; ++ siginfo_t status = {}; ++ struct timespec ts; ++ ++ n = now(CLOCK_MONOTONIC); ++ if (n >= until) ++ break; ++ ++ r = sigtimedwait(&mask, NULL, timespec_store(&ts, until - n)) < 0 ? -errno : 0; ++ /* Assuming we woke due to the child exiting. */ ++ if (waitid(P_PID, pid, &status, WEXITED|WNOHANG) == 0) { ++ if (status.si_pid == pid) { ++ /* This is the correct child.*/ ++ if (status.si_code == CLD_EXITED) ++ return (status.si_status == 0) ? 0 : -EPROTO; ++ else ++ return -EPROTO; ++ } ++ } ++ /* Not the child, check for errors and proceed appropriately */ ++ if (r < 0) { ++ switch (r) { ++ case -EAGAIN: ++ /* Timed out, child is likely hung. */ ++ return -ETIMEDOUT; ++ case -EINTR: ++ /* Received a different signal and should retry */ ++ continue; ++ default: ++ /* Return any unexpected errors */ ++ return r; ++ } ++ } ++ } ++ ++ return -EPROTO; ++} +diff --git a/src/shared/util.h b/src/shared/util.h +index 9c4be0256..998f882bb 100644 +--- a/src/shared/util.h ++++ b/src/shared/util.h +@@ -22,6 +22,7 @@ + ***/ + + #include ++#include + #include + #include + #include +@@ -1122,3 +1123,18 @@ enum { + }; + + int acquire_data_fd(const void *data, size_t size, unsigned flags); ++ ++int wait_for_terminate_with_timeout(pid_t pid, usec_t timeout); ++ ++static inline void block_signals_reset(sigset_t *ss) { ++ assert_se(sigprocmask(SIG_SETMASK, ss, NULL) >= 0); ++} ++ ++#define BLOCK_SIGNALS(...) \ ++ _cleanup_(block_signals_reset) _unused_ sigset_t _saved_sigset = ({ \ ++ sigset_t _t; \ ++ assert_se(sigprocmask(SIG_SETMASK, NULL, &_t) == 0); \ ++ assert_se(sigprocmask_many(SIG_BLOCK, __VA_ARGS__, -1) >= 0); \ ++ _t; \ ++ }) ++ diff --git a/SOURCES/0641-core-Implement-sync_with_progress.patch b/SOURCES/0641-core-Implement-sync_with_progress.patch new file mode 100644 index 00000000..bbadec63 --- /dev/null +++ b/SOURCES/0641-core-Implement-sync_with_progress.patch @@ -0,0 +1,169 @@ +From db57bf73d3e5e650b261834a0c39c9d368f9eeea Mon Sep 17 00:00:00 2001 +From: Kyle Walker +Date: Thu, 14 Dec 2017 11:46:03 -0500 +Subject: [PATCH] core: Implement sync_with_progress() + +In similar fashion to the previous change, sync() operations can stall +endlessly if cache is unable to be written out. In order to avoid an +unbounded hang, the sync takes place within a child process. Every 10 +seconds (SYNC_TIMEOUT_USEC), the value of /proc/meminfo "Dirty" is checked +to verify it is smaller than the last iteration. If the sync is not making +progress for 3 successive iterations (SYNC_PROGRESS_ATTEMPTS), a SIGKILL is +sent to the sync process and the shutdown continues. + +(cherry picked from commit 73ad712fcfea5d8ba475044698d31d2c15d4180d) + +Related: #1571098 +--- + src/core/shutdown.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 111 insertions(+), 5 deletions(-) + +diff --git a/src/core/shutdown.c b/src/core/shutdown.c +index 71f001ac1..0b0a54a7d 100644 +--- a/src/core/shutdown.c ++++ b/src/core/shutdown.c +@@ -53,6 +53,9 @@ + + #define FINALIZE_ATTEMPTS 50 + ++#define SYNC_PROGRESS_ATTEMPTS 3 ++#define SYNC_TIMEOUT_USEC (10*USEC_PER_SEC) ++ + static char* arg_verb; + + static int parse_argv(int argc, char *argv[]) { +@@ -152,6 +155,102 @@ static int switch_root_initramfs(void) { + return switch_root("/run/initramfs", "/oldroot", false, MS_BIND); + } + ++/* Read the following fields from /proc/meminfo: ++ * ++ * NFS_Unstable ++ * Writeback ++ * Dirty ++ * ++ * Return true if the sum of these fields is greater than the previous ++ * value input. For all other issues, report the failure and indicate that ++ * the sync is not making progress. ++ */ ++static bool sync_making_progress(unsigned long long *prev_dirty) { ++ _cleanup_fclose_ FILE *f = NULL; ++ char line[LINE_MAX]; ++ bool r = false; ++ unsigned long long val = 0; ++ ++ f = fopen("/proc/meminfo", "re"); ++ if (!f) ++ return log_warning_errno(errno, "Failed to open /proc/meminfo: %m"); ++ ++ FOREACH_LINE(line, f, log_warning_errno(errno, "Failed to parse /proc/meminfo: %m")) { ++ unsigned long long ull = 0; ++ ++ if (!first_word(line, "NFS_Unstable:") && !first_word(line, "Writeback:") && !first_word(line, "Dirty:")) ++ continue; ++ ++ errno = 0; ++ if (sscanf(line, "%*s %llu %*s", &ull) != 1) { ++ if (errno != 0) ++ log_warning_errno(errno, "Failed to parse /proc/meminfo: %m"); ++ else ++ log_warning("Failed to parse /proc/meminfo"); ++ ++ return false; ++ } ++ ++ val += ull; ++ } ++ ++ r = *prev_dirty > val; ++ ++ *prev_dirty = val; ++ ++ return r; ++} ++ ++static void sync_with_progress(void) { ++ unsigned checks; ++ pid_t pid; ++ int r; ++ unsigned long long dirty = ULONG_LONG_MAX; ++ ++ BLOCK_SIGNALS(SIGCHLD); ++ ++ /* Due to the possiblity of the sync operation hanging, we fork ++ * a child process and monitor the progress. If the timeout ++ * lapses, the assumption is that that particular sync stalled. */ ++ pid = fork(); ++ if (pid < 0) { ++ log_error_errno(errno, "Failed to fork: %m"); ++ return; ++ } ++ ++ if (pid == 0) { ++ /* Start the sync operation here in the child */ ++ sync(); ++ _exit(EXIT_SUCCESS); ++ } ++ ++ log_info("Syncing filesystems and block devices."); ++ ++ /* Start monitoring the sync operation. If more than ++ * SYNC_PROGRESS_ATTEMPTS lapse without progress being made, ++ * we assume that the sync is stalled */ ++ for (checks = 0; checks < SYNC_PROGRESS_ATTEMPTS; checks++) { ++ r = wait_for_terminate_with_timeout(pid, SYNC_TIMEOUT_USEC); ++ if (r == 0) ++ /* Sync finished without error. ++ * (The sync itself does not return an error code) */ ++ return; ++ else if (r == -ETIMEDOUT) { ++ /* Reset the check counter if the "Dirty" value is ++ * decreasing */ ++ if (sync_making_progress(&dirty)) ++ checks = 0; ++ } else { ++ log_error_errno(r, "Failed to sync filesystems and block devices: %m"); ++ return; ++ } ++ } ++ ++ /* Only reached in the event of a timeout. We should issue a kill ++ * to the stray process. */ ++ log_error("Syncing filesystems and block devices - timed out, issuing SIGKILL to PID "PID_FMT".", pid); ++ (void) kill(pid, SIGKILL); ++} + + int main(int argc, char *argv[]) { + bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; +@@ -202,6 +301,13 @@ int main(int argc, char *argv[]) { + /* lock us into memory */ + mlockall(MCL_CURRENT|MCL_FUTURE); + ++ /* Synchronize everything that is not written to disk yet at this point already. This is a good idea so that ++ * slow IO is processed here already and the final process killing spree is not impacted by processes ++ * desperately trying to sync IO to disk within their timeout. Do not remove this sync, data corruption will ++ * result. */ ++ if (!in_container) ++ sync_with_progress(); ++ + log_info("Sending SIGTERM to remaining processes..."); + broadcast_signal(SIGTERM, true, true); + +@@ -338,12 +444,12 @@ int main(int argc, char *argv[]) { + need_loop_detach ? " loop devices," : "", + need_dm_detach ? " DM devices," : ""); + +- /* The kernel will automaticall flush ATA disks and suchlike +- * on reboot(), but the file systems need to be synce'd +- * explicitly in advance. So let's do this here, but not +- * needlessly slow down containers. */ ++ /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be ++ * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we ++ * sync'ed things already once above, but we did some more work since then which might have caused IO, hence ++ * let's do it once more. Do not remove this sync, data corruption will result. */ + if (!in_container) +- sync(); ++ sync_with_progress(); + + switch (cmd) { + diff --git a/SOURCES/0642-journal-fix-HMAC-calculation-when-appending-a-data-o.patch b/SOURCES/0642-journal-fix-HMAC-calculation-when-appending-a-data-o.patch new file mode 100644 index 00000000..0a341654 --- /dev/null +++ b/SOURCES/0642-journal-fix-HMAC-calculation-when-appending-a-data-o.patch @@ -0,0 +1,48 @@ +From 4f36220ccfe40621cd7df3595568278d7bca4f87 Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Fri, 23 Sep 2016 13:33:01 +0200 +Subject: [PATCH] journal: fix HMAC calculation when appending a data object + +Since commit 5996c7c295e073ce21d41305169132c8aa993ad0 (v190 !), the +calculation of the HMAC is broken because the hash for a data object +including a field is done in the wrong order: the field object is +hashed before the data object is. + +However during verification, the hash is done in the opposite order as +objects are scanned sequentially. + +(cherry picked from commit 33685a5a3a98c6ded64d0cc25e37d0180ceb0a6a) +--- + src/journal/journal-file.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c +index 2bb3a9757..586f620e2 100644 +--- a/src/journal/journal-file.c ++++ b/src/journal/journal-file.c +@@ -1099,6 +1099,12 @@ static int journal_file_append_data( + if (r < 0) + return r; + ++#ifdef HAVE_GCRYPT ++ r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); ++ if (r < 0) ++ return r; ++#endif ++ + /* The linking might have altered the window, so let's + * refresh our pointer */ + r = journal_file_move_to_object(f, OBJECT_DATA, p, &o); +@@ -1123,12 +1129,6 @@ static int journal_file_append_data( + fo->field.head_data_offset = le64toh(p); + } + +-#ifdef HAVE_GCRYPT +- r = journal_file_hmac_put_object(f, OBJECT_DATA, o, p); +- if (r < 0) +- return r; +-#endif +- + if (ret) + *ret = o; + diff --git a/SOURCES/0643-journal-forward-messages-from-dev-log-unmodified-to-.patch b/SOURCES/0643-journal-forward-messages-from-dev-log-unmodified-to-.patch new file mode 100644 index 00000000..75fd731d --- /dev/null +++ b/SOURCES/0643-journal-forward-messages-from-dev-log-unmodified-to-.patch @@ -0,0 +1,135 @@ +From d82c40a2377b487ef83aa1fb907ec275a1b3e86e Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 30 May 2018 16:27:22 +0200 +Subject: [PATCH] journal: forward messages from /dev/log unmodified to + syslog.socket + +(cherry picked from commit bb3ff70a86faff85fe482995c8ba5332b1a34f76) + +Resolves: #1409659 +--- + src/journal/journald-server.c | 2 +- + src/journal/journald-syslog.c | 39 +++++++++++++++++++++++++-------------- + src/journal/journald-syslog.h | 2 +- + 3 files changed, 27 insertions(+), 16 deletions(-) + +diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c +index 7c69061f4..7e67e055e 100644 +--- a/src/journal/journald-server.c ++++ b/src/journal/journald-server.c +@@ -1294,7 +1294,7 @@ int server_process_datagram(sd_event_source *es, int fd, uint32_t revents, void + + if (fd == s->syslog_fd) { + if (n > 0 && n_fds == 0) +- server_process_syslog_message(s, strstrip(s->buffer), ucred, tv, label, label_len); ++ server_process_syslog_message(s, s->buffer, n, ucred, tv, label, label_len); + else if (n_fds > 0) + log_warning("Got file descriptors via syslog socket. Ignoring."); + +diff --git a/src/journal/journald-syslog.c b/src/journal/journald-syslog.c +index b499a0d38..01d2bf69f 100644 +--- a/src/journal/journald-syslog.c ++++ b/src/journal/journald-syslog.c +@@ -109,7 +109,7 @@ static void forward_syslog_iovec(Server *s, const struct iovec *iovec, unsigned + log_debug_errno(errno, "Failed to forward syslog message: %m"); + } + +-static void forward_syslog_raw(Server *s, int priority, const char *buffer, const struct ucred *ucred, const struct timeval *tv) { ++static void forward_syslog_raw(Server *s, int priority, const char *buffer, size_t buffer_len, const struct ucred *ucred, const struct timeval *tv) { + struct iovec iovec; + + assert(s); +@@ -118,7 +118,9 @@ static void forward_syslog_raw(Server *s, int priority, const char *buffer, cons + if (LOG_PRI(priority) > s->max_level_syslog) + return; + +- IOVEC_SET_STRING(iovec, buffer); ++ iovec.iov_base = (char *) buffer; ++ iovec.iov_len = buffer_len; ++ + forward_syslog_iovec(s, &iovec, 1, ucred, tv); + } + +@@ -311,40 +313,49 @@ static void syslog_skip_date(char **buf) { + void server_process_syslog_message( + Server *s, + const char *buf, ++ size_t buf_len, + const struct ucred *ucred, + const struct timeval *tv, + const char *label, + size_t label_len) { + + char syslog_priority[sizeof("PRIORITY=") + DECIMAL_STR_MAX(int)], +- syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)]; ++ syslog_facility[sizeof("SYSLOG_FACILITY=") + DECIMAL_STR_MAX(int)], *msg; + const char *message = NULL, *syslog_identifier = NULL, *syslog_pid = NULL; + struct iovec iovec[N_IOVEC_META_FIELDS + 6]; +- unsigned n = 0; ++ unsigned n = 0, i; + int priority = LOG_USER | LOG_INFO; + _cleanup_free_ char *identifier = NULL, *pid = NULL; +- const char *orig; + + assert(s); + assert(buf); + +- orig = buf; +- syslog_parse_priority(&buf, &priority, true); ++ /* We are creating copy of the message because we want to forward original message verbatim to the legacy ++ syslog implementation */ ++ for (i = buf_len; i > 0; i--) ++ if (!strchr(WHITESPACE, buf[i-1])) ++ break; ++ ++ msg = newa(char, i + 1); ++ *((char *) mempcpy(msg, buf, i)) = 0; ++ msg += strspn(msg, WHITESPACE); ++ ++ syslog_parse_priority((const char **)&msg, &priority, true); + + if (s->forward_to_syslog) +- forward_syslog_raw(s, priority, orig, ucred, tv); ++ forward_syslog_raw(s, priority, buf, buf_len, ucred, tv); + +- syslog_skip_date((char**) &buf); +- syslog_parse_identifier(&buf, &identifier, &pid); ++ syslog_skip_date(&msg); ++ syslog_parse_identifier((const char**)&msg, &identifier, &pid); + + if (s->forward_to_kmsg) +- server_forward_kmsg(s, priority, identifier, buf, ucred); ++ server_forward_kmsg(s, priority, identifier, msg, ucred); + + if (s->forward_to_console) +- server_forward_console(s, priority, identifier, buf, ucred); ++ server_forward_console(s, priority, identifier, msg, ucred); + + if (s->forward_to_wall) +- server_forward_wall(s, priority, identifier, buf, ucred); ++ server_forward_wall(s, priority, identifier, msg, ucred); + + IOVEC_SET_STRING(iovec[n++], "_TRANSPORT=syslog"); + +@@ -368,7 +379,7 @@ void server_process_syslog_message( + IOVEC_SET_STRING(iovec[n++], syslog_pid); + } + +- message = strjoina("MESSAGE=", buf); ++ message = strjoina("MESSAGE=", msg); + if (message) + IOVEC_SET_STRING(iovec[n++], message); + +diff --git a/src/journal/journald-syslog.h b/src/journal/journald-syslog.h +index 3774ebdf0..e593be99a 100644 +--- a/src/journal/journald-syslog.h ++++ b/src/journal/journald-syslog.h +@@ -29,7 +29,7 @@ size_t syslog_parse_identifier(const char **buf, char **identifier, char **pid); + + void server_forward_syslog(Server *s, int priority, const char *identifier, const char *message, const struct ucred *ucred, const struct timeval *tv); + +-void server_process_syslog_message(Server *s, const char *buf, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); ++void server_process_syslog_message(Server *s, const char *buf, size_t buf_len, const struct ucred *ucred, const struct timeval *tv, const char *label, size_t label_len); + int server_open_syslog_socket(Server *s); + + void server_maybe_warn_forward_syslog_missed(Server *s); diff --git a/SOURCES/0644-tmpfiles-use-safe_glob.patch b/SOURCES/0644-tmpfiles-use-safe_glob.patch new file mode 100644 index 00000000..65b1fce2 --- /dev/null +++ b/SOURCES/0644-tmpfiles-use-safe_glob.patch @@ -0,0 +1,158 @@ +From 2f9ee3163c44a71c99fe104daf01d4d9ab51d2c9 Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Mon, 28 May 2018 10:52:52 +0200 +Subject: [PATCH] tmpfiles: use safe_glob() + +This filters out "." and ".." from glob results. Fixes #5655 and #5644. + +Any judgements on whether the path is "safe" are removed. We will not remove +"/" under any name (including "/../" and such), but we will remove stuff that +is specified using paths that include "//", "/./" and "/../". Such paths can be +created when joining strings automatically, or for other reasons, and people +generally know what ".." and "." is. + +Tests are added to make sure that the helper functions behave as expected. + +Original commit: 84e72b5ef445ffb256bc4add4209c4c9c9855206 +Resolves: #1436004 +--- + src/shared/util.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++-- + src/shared/util.h | 2 ++ + src/tmpfiles/tmpfiles.c | 11 +++------ + 3 files changed, 66 insertions(+), 10 deletions(-) + +diff --git a/src/shared/util.c b/src/shared/util.c +index 3216f004a..78967103a 100644 +--- a/src/shared/util.c ++++ b/src/shared/util.c +@@ -49,7 +49,6 @@ + #include + #include + #include +-#include + #include + #include + #include +@@ -3370,7 +3369,7 @@ static int rm_rf_internal(const char *path, bool only_dirs, bool delete_root, bo + /* We refuse to clean the root file system with this + * call. This is extra paranoia to never cause a really + * seriously broken system. */ +- if (path_equal(path, "/")) { ++ if (path_equal_or_files_same(path, "/")) { + log_error("Attempted to remove entire root file system, and we can't allow that."); + return -EPERM; + } +@@ -5096,6 +5095,66 @@ int in_group(const char *name) { + return in_gid(gid); + } + ++static void closedir_wrapper(void* v) { ++ (void) closedir(v); ++} ++ ++static bool dot_or_dot_dot(const char *path) { ++ if (!path) ++ return false; ++ if (path[0] != '.') ++ return false; ++ if (path[1] == 0) ++ return true; ++ if (path[1] != '.') ++ return false; ++ ++ return path[2] == 0; ++} ++ ++static struct dirent* readdir_no_dot(DIR *dirp) { ++ struct dirent* d; ++ ++ for (;;) { ++ d = readdir(dirp); ++ if (d && dot_or_dot_dot(d->d_name)) ++ continue; ++ return d; ++ } ++} ++ ++int safe_glob(const char *path, int flags, glob_t *pglob) { ++ int k; ++ ++ /* We want to set GLOB_ALTDIRFUNC ourselves, don't allow it to be set. */ ++ assert(!(flags & GLOB_ALTDIRFUNC)); ++ ++ if (!pglob->gl_closedir) ++ pglob->gl_closedir = closedir_wrapper; ++ if (!pglob->gl_readdir) ++ pglob->gl_readdir = (struct dirent *(*)(void *)) readdir_no_dot; ++ if (!pglob->gl_opendir) ++ pglob->gl_opendir = (void *(*)(const char *)) opendir; ++ if (!pglob->gl_lstat) ++ pglob->gl_lstat = lstat; ++ if (!pglob->gl_stat) ++ pglob->gl_stat = stat; ++ ++ errno = 0; ++ k = glob(path, flags | GLOB_ALTDIRFUNC, NULL, pglob); ++ ++ if (k == GLOB_NOMATCH) ++ return -ENOENT; ++ if (k == GLOB_NOSPACE) ++ return -ENOMEM; ++ if (k != 0) ++ return errno > 0 ? -errno : -EIO; ++ if (strv_isempty(pglob->gl_pathv)) ++ return -ENOENT; ++ ++ return 0; ++} ++ + int glob_exists(const char *path) { + _cleanup_globfree_ glob_t g = {}; + int k; +diff --git a/src/shared/util.h b/src/shared/util.h +index 998f882bb..cf096aa07 100644 +--- a/src/shared/util.h ++++ b/src/shared/util.h +@@ -44,6 +44,7 @@ + #include + #include + #include ++#include + + #if SIZEOF_PID_T == 4 + # define PID_PRI PRIi32 +@@ -595,6 +596,7 @@ char* gid_to_name(gid_t gid); + + int glob_exists(const char *path); + int glob_extend(char ***strv, const char *path); ++int safe_glob(const char *path, int flags, glob_t *pglob); + + int dirent_ensure_type(DIR *d, struct dirent *de); + +diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c +index 5212d72f5..8a75efb22 100644 +--- a/src/tmpfiles/tmpfiles.c ++++ b/src/tmpfiles/tmpfiles.c +@@ -1095,19 +1095,14 @@ static int item_do_children(Item *i, const char *path, action_t action) { + + static int glob_item(Item *i, action_t action, bool recursive) { + _cleanup_globfree_ glob_t g = { +- .gl_closedir = (void (*)(void *)) closedir, +- .gl_readdir = (struct dirent *(*)(void *)) readdir, + .gl_opendir = (void *(*)(const char *)) opendir_nomod, +- .gl_lstat = lstat, +- .gl_stat = stat, + }; + int r = 0, k; + char **fn; + +- errno = 0; +- k = glob(i->path, GLOB_NOSORT|GLOB_BRACE|GLOB_ALTDIRFUNC, NULL, &g); +- if (k != 0 && k != GLOB_NOMATCH) +- return log_error_errno(errno ?: EIO, "glob(%s) failed: %m", i->path); ++ k = safe_glob(i->path, GLOB_NOSORT|GLOB_BRACE, &g); ++ if (k < 0 && k != -ENOENT) ++ return log_error_errno(k, "glob(%s) failed: %m", i->path); + + STRV_FOREACH(fn, g.gl_pathv) { + k = action(i, *fn); diff --git a/SOURCES/0645-Fix-SELinux-labels-in-cgroup-filesystem-root-directo.patch b/SOURCES/0645-Fix-SELinux-labels-in-cgroup-filesystem-root-directo.patch new file mode 100644 index 00000000..76c05e5d --- /dev/null +++ b/SOURCES/0645-Fix-SELinux-labels-in-cgroup-filesystem-root-directo.patch @@ -0,0 +1,52 @@ +From c043ae5b2ef2e1e437bf738bbf522799c6213230 Mon Sep 17 00:00:00 2001 +From: Krzysztof Nowicki +Date: Thu, 30 Nov 2017 11:59:29 +0100 +Subject: [PATCH] Fix SELinux labels in cgroup filesystem root directory + (#7496) + +When using SELinux with legacy cgroups the tmpfs on /sys/fs/cgroup is by +default labelled as tmpfs_t. This label is also inherited by the "cpu" +and "cpuacct" symbolic links. Unfortunately the policy expects them to +be labelled as cgroup_t, which is used for all the actual cgroup +filesystems. Failure to do so results in a stream of denials. + +This state cannot be fixed reliably when the cgroup filesystem structure +is set-up as the SELinux policy is not yet loaded at this +moment. It also cannot be fixed later as the root of the cgroup +filesystem is remounted read-only. In order to fix it the root of the +cgroup filesystem needs to be temporary remounted read-write, relabelled +and remounted back read-only. + +(cherry picked from commit 8739f23e3c26bbf8b0296421578e56daa63cbf4b) +--- + src/core/mount-setup.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index 521545e5c..7a2cae4a3 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -363,14 +363,22 @@ int mount_setup(bool loaded_policy) { + usec_t before_relabel, after_relabel; + char timespan[FORMAT_TIMESPAN_MAX]; + ++ mkdir_label("/run/systemd/policy-relabelling", 0755); + before_relabel = now(CLOCK_MONOTONIC); + + nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + ++ /* Temporarily remount the root cgroup filesystem to give it a proper label. */ ++ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); ++ label_fix("/sys/fs/cgroup", false, false); ++ nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); ++ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); ++ + after_relabel = now(CLOCK_MONOTONIC); + +- log_info("Relabelled /dev and /run in %s.", ++ mkdir_label("/run/systemd/policy-relabelled", 0755); ++ log_info("Relabelled /dev, /run and /sys/fs/cgroup in %s.", + format_timespan(timespan, sizeof(timespan), after_relabel - before_relabel, 0)); + } + #endif diff --git a/SOURCES/0646-core-dont-t-remount-sys-fs-cgroup-for-relabel-if-not.patch b/SOURCES/0646-core-dont-t-remount-sys-fs-cgroup-for-relabel-if-not.patch new file mode 100644 index 00000000..0a3f6e4c --- /dev/null +++ b/SOURCES/0646-core-dont-t-remount-sys-fs-cgroup-for-relabel-if-not.patch @@ -0,0 +1,91 @@ +From 1707b9959e67e5e73987e1ff8a72189d24656fa0 Mon Sep 17 00:00:00 2001 +From: Krzysztof Nowicki +Date: Wed, 28 Mar 2018 13:36:33 +0200 +Subject: [PATCH] core: dont't remount /sys/fs/cgroup for relabel if not needed + (#8595) + +The initial fix for relabelling the cgroup filesystem for +SELinux delivered in commit 8739f23e3 was based on the assumption that +the cgroup filesystem is already populated once mount_setup() is +executed, which was true for my system. What I wasn't aware is that this +is the case only when another instance of systemd was running before +this one, which can happen if systemd is used in the initrd (for ex. by +dracut). + +In case of a clean systemd start-up the cgroup filesystem is actually +being populated after mount_setup() and does not need relabelling as at +that moment the SELinux policy is already loaded. Since however the root +cgroup filesystem was remounted read-only in the meantime this operation +will now fail. + +To fix this check for the filesystem mount flags before relabelling and +only remount ro->rw->ro if necessary and leave the filesystem read-write +otherwise. + +Fixes #7901. + +(cherry picked from commit 6f7729c1767998110c4460c85c94435c5782a613) +--- + src/core/mount-setup.c | 35 ++++++++++++++++++++++++++++++----- + 1 file changed, 30 insertions(+), 5 deletions(-) + +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index 7a2cae4a3..ed493cbe3 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -25,6 +25,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -337,6 +339,31 @@ static int nftw_cb( + + return FTW_CONTINUE; + }; ++ ++static int relabel_cgroup_filesystems(void) { ++ int r; ++ struct statfs st; ++ ++ /* Temporarily remount the root cgroup filesystem to give it a proper label. Do this ++ only when the filesystem has been already populated by a previous instance of systemd ++ running from initrd. Otherwise don't remount anything and leave the filesystem read-write ++ for the cgroup filesystems to be mounted inside. */ ++ r = statfs("/sys/fs/cgroup", &st); ++ if (r < 0) { ++ return log_error_errno(errno, "Failed to determine mount flags for /sys/fs/cgroup: %m"); ++ } ++ ++ if (st.f_flags & ST_RDONLY) ++ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); ++ ++ (void) label_fix("/sys/fs/cgroup", false, false); ++ nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); ++ ++ if (st.f_flags & ST_RDONLY) ++ (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); ++ ++ return 0; ++} + #endif + + int mount_setup(bool loaded_policy) { +@@ -369,11 +396,9 @@ int mount_setup(bool loaded_policy) { + nftw("/dev", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + nftw("/run", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); + +- /* Temporarily remount the root cgroup filesystem to give it a proper label. */ +- (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT, NULL); +- label_fix("/sys/fs/cgroup", false, false); +- nftw("/sys/fs/cgroup", nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); +- (void) mount(NULL, "/sys/fs/cgroup", NULL, MS_REMOUNT|MS_RDONLY, NULL); ++ r = relabel_cgroup_filesystems(); ++ if (r < 0) ++ return r; + + after_relabel = now(CLOCK_MONOTONIC); + diff --git a/SOURCES/0647-fix-race-between-daemon-reload-and-other-commands.patch b/SOURCES/0647-fix-race-between-daemon-reload-and-other-commands.patch new file mode 100644 index 00000000..088800a9 --- /dev/null +++ b/SOURCES/0647-fix-race-between-daemon-reload-and-other-commands.patch @@ -0,0 +1,188 @@ +From 13bcf85ffab4b4e67039599246604a3f5b503975 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Tue, 24 Apr 2018 15:19:38 +0200 +Subject: [PATCH] fix race between daemon-reload and other commands + +When "systemctl daemon-reload" is run at the same time as "systemctl +start foo", the latter might hang. That's because commands like start +wait for JobRemoved signal to know when the job is finished. But if the +job is finished during reloading, the signal is never sent. + +The hang can be easily reproduced by running + + # for ((N=1; N>0; N++)) ; do echo $N ; systemctl daemon-reload ; done + # for ((N=1; N>0; N++)) ; do echo $N ; systemctl start systemd-coredump.socket ; done + +in two different terminals. The start command will hang after 1-2 +iterations. + +This keeps track of jobs that were started before reload and finished +during it and sends JobRemoved after the reload has finished. + +(cherry picked from commit a7a7163df7fc8a9f794f6803b2f6c9c9b0745a1f) +--- + src/core/job.c | 45 ++++++++++++++++++++++++++++++++++++++++----- + src/core/job.h | 2 ++ + src/core/manager.c | 15 +++++++++++++++ + src/core/manager.h | 3 +++ + 4 files changed, 60 insertions(+), 5 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index 1861c8a63..275503169 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -53,6 +53,7 @@ Job* job_new_raw(Unit *unit) { + j->manager = unit->manager; + j->unit = unit; + j->type = _JOB_TYPE_INVALID; ++ j->reloaded = false; + + return j; + } +@@ -74,7 +75,7 @@ Job* job_new(Unit *unit, JobType type) { + return j; + } + +-void job_free(Job *j) { ++void job_unlink(Job *j) { + assert(j); + assert(!j->installed); + assert(!j->transaction_prev); +@@ -82,13 +83,28 @@ void job_free(Job *j) { + assert(!j->subject_list); + assert(!j->object_list); + +- if (j->in_run_queue) ++ if (j->in_run_queue) { + LIST_REMOVE(run_queue, j->manager->run_queue, j); ++ j->in_run_queue = false; ++ } + +- if (j->in_dbus_queue) ++ if (j->in_dbus_queue) { + LIST_REMOVE(dbus_queue, j->manager->dbus_job_queue, j); ++ j->in_dbus_queue = false; ++ } ++ ++ j->timer_event_source = sd_event_source_unref(j->timer_event_source); ++} ++ ++void job_free(Job *j) { ++ assert(j); ++ assert(!j->installed); ++ assert(!j->transaction_prev); ++ assert(!j->transaction_next); ++ assert(!j->subject_list); ++ assert(!j->object_list); + +- sd_event_source_unref(j->timer_event_source); ++ job_unlink(j); + + sd_bus_track_unref(j->clients); + strv_free(j->deserialized_clients); +@@ -246,6 +262,7 @@ int job_install_deserialized(Job *j) { + + *pj = j; + j->installed = true; ++ j->reloaded = true; + + if (j->state == JOB_RUNNING) + j->unit->manager->n_running_jobs++; +@@ -790,6 +807,19 @@ static void job_emit_status_message(Unit *u, JobType t, JobResult result) { + job_print_status_message(u, t, result); + } + ++static int job_save_pending_finished_job(Job *j) { ++ int r; ++ ++ assert(j); ++ ++ r = set_ensure_allocated(&j->manager->pending_finished_jobs, NULL); ++ if (r < 0) ++ return r; ++ ++ job_unlink(j); ++ return set_put(j->manager->pending_finished_jobs, j); ++} ++ + int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool already) { + Unit *u; + Unit *other; +@@ -829,7 +859,12 @@ int job_finish_and_invalidate(Job *j, JobResult result, bool recursive, bool alr + j->manager->n_failed_jobs ++; + + job_uninstall(j); +- job_free(j); ++ /* Remember jobs started before the reload */ ++ if (j->manager->n_reloading > 0 && j->reloaded) { ++ if (job_save_pending_finished_job(j) < 0) ++ job_free(j); ++ } else ++ job_free(j); + + /* Fail depending jobs on failure */ + if (result != JOB_DONE && recursive) { +diff --git a/src/core/job.h b/src/core/job.h +index 535052b48..4ae6f2802 100644 +--- a/src/core/job.h ++++ b/src/core/job.h +@@ -172,10 +172,12 @@ struct Job { + bool sent_dbus_new_signal:1; + bool ignore_order:1; + bool irreversible:1; ++ bool reloaded:1; + }; + + Job* job_new(Unit *unit, JobType type); + Job* job_new_raw(Unit *unit); ++void job_unlink(Job *job); + void job_free(Job *job); + Job* job_install(Job *j); + int job_install_deserialized(Job *j); +diff --git a/src/core/manager.c b/src/core/manager.c +index 47b09e1e9..9c406bb5b 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -2702,6 +2702,18 @@ finish: + return r; + } + ++static void manager_flush_finished_jobs(Manager *m) { ++ Job *j; ++ ++ while ((j = set_steal_first(m->pending_finished_jobs))) { ++ bus_job_send_removed_signal(j); ++ job_free(j); ++ } ++ ++ set_free(m->pending_finished_jobs); ++ m->pending_finished_jobs = NULL; ++} ++ + int manager_reload(Manager *m) { + int r, q; + _cleanup_fclose_ FILE *f = NULL; +@@ -2784,6 +2796,9 @@ int manager_reload(Manager *m) { + assert(m->n_reloading > 0); + m->n_reloading--; + ++ if (m->n_reloading <= 0) ++ manager_flush_finished_jobs(m); ++ + m->send_reloading_done = true; + + return r; +diff --git a/src/core/manager.h b/src/core/manager.h +index e91e7bd8b..90d2d982e 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -270,6 +270,9 @@ struct Manager { + + /* non-zero if we are reloading or reexecuting, */ + int n_reloading; ++ /* A set which contains all jobs that started before reload and finished ++ * during it */ ++ Set *pending_finished_jobs; + + unsigned n_installed_jobs; + unsigned n_failed_jobs; diff --git a/SOURCES/0648-core-delay-adding-target-dependencies-until-all-unit.patch b/SOURCES/0648-core-delay-adding-target-dependencies-until-all-unit.patch new file mode 100644 index 00000000..4145956a --- /dev/null +++ b/SOURCES/0648-core-delay-adding-target-dependencies-until-all-unit.patch @@ -0,0 +1,223 @@ +From 36226a9afe96bdffce9d0697be020f2ca9d7fe6f Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 23 Mar 2018 15:28:06 +0100 +Subject: [PATCH] core: delay adding target dependencies until all units are + loaded and aliases resolved (#8381) + +Currently we add target dependencies while we are loading units. This +can create ordering loops even if configuration doesn't contain any +loop. Take for example following configuration, + +$ systemctl get-default +multi-user.target + +$ cat /etc/systemd/system/test.service +[Unit] +After=default.target + +[Service] +ExecStart=/bin/true + +[Install] +WantedBy=multi-user.target + +If we encounter such unit file early during manager start-up (e.g. load +queue is dispatched while enumerating devices due to SYSTEMD_WANTS in +udev rules) we would add stub unit default.target and we order it Before +test.service. At the same time we add implicit Before to +multi-user.target. Later we merge two units and we create ordering cycle +in the process. + +To fix the issue we will now never add any target dependencies until we +loaded all the unit files and resolved all the aliases. + +(cherry picked from commit 19496554e23ea4861ce780430052dcf86a2ffcba) + +Resolves: #1368856 +--- + src/core/manager.c | 40 ++++++++++++++++++++++++++++++++++++++++ + src/core/manager.h | 3 +++ + src/core/unit.c | 46 ++++++++++++++++------------------------------ + src/core/unit.h | 5 +++++ + 4 files changed, 64 insertions(+), 30 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 9c406bb5b..0466e4bb8 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -1373,6 +1373,41 @@ Unit *manager_get_unit(Manager *m, const char *name) { + return hashmap_get(m->units, name); + } + ++static int manager_dispatch_target_deps_queue(Manager *m) { ++ Unit *u; ++ unsigned k; ++ int r = 0; ++ ++ static const UnitDependency deps[] = { ++ UNIT_REQUIRED_BY, ++ UNIT_REQUIRED_BY_OVERRIDABLE, ++ UNIT_WANTED_BY, ++ UNIT_BOUND_BY ++ }; ++ ++ assert(m); ++ ++ while ((u = m->target_deps_queue)) { ++ assert(u->in_target_deps_queue); ++ ++ LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); ++ u->in_target_deps_queue = false; ++ ++ for (k = 0; k < ELEMENTSOF(deps); k++) { ++ Unit *target; ++ Iterator i; ++ ++ SET_FOREACH(target, u->dependencies[deps[k]], i) { ++ r = unit_add_default_target_dependency(u, target); ++ if (r < 0) ++ return r; ++ } ++ } ++ } ++ ++ return r; ++} ++ + unsigned manager_dispatch_load_queue(Manager *m) { + Unit *u; + unsigned n = 0; +@@ -1396,6 +1431,11 @@ unsigned manager_dispatch_load_queue(Manager *m) { + } + + m->dispatching_load_queue = false; ++ ++ /* Dispatch the units waiting for their target dependencies to be added now, as all targets that we know about ++ * should be loaded and have aliases resolved */ ++ (void) manager_dispatch_target_deps_queue(m); ++ + return n; + } + +diff --git a/src/core/manager.h b/src/core/manager.h +index 90d2d982e..b0e4cad1f 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -114,6 +114,9 @@ struct Manager { + /* Units that should be realized */ + LIST_HEAD(Unit, cgroup_queue); + ++ /* Target units whose default target dependencies haven't been set yet */ ++ LIST_HEAD(Unit, target_deps_queue); ++ + sd_event *event; + + /* We use two hash tables here, since the same PID might be +diff --git a/src/core/unit.c b/src/core/unit.c +index 22d9beed7..cfddce34d 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -519,6 +519,9 @@ void unit_free(Unit *u) { + u->manager->n_in_gc_queue--; + } + ++ if (u->in_target_deps_queue) ++ LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); ++ + if (u->in_cgroup_queue) + LIST_REMOVE(cgroup_queue, u->manager->cgroup_queue, u); + +@@ -1065,6 +1068,18 @@ int unit_load_fragment_and_dropin_optional(Unit *u) { + return 0; + } + ++void unit_add_to_target_deps_queue(Unit *u) { ++ Manager *m = u->manager; ++ ++ assert(u); ++ ++ if (u->in_target_deps_queue) ++ return; ++ ++ LIST_PREPEND(target_deps_queue, m->target_deps_queue, u); ++ u->in_target_deps_queue = true; ++} ++ + int unit_add_default_target_dependency(Unit *u, Unit *target) { + assert(u); + assert(target); +@@ -1091,32 +1106,6 @@ int unit_add_default_target_dependency(Unit *u, Unit *target) { + return unit_add_dependency(target, UNIT_AFTER, u, true); + } + +-static int unit_add_target_dependencies(Unit *u) { +- +- static const UnitDependency deps[] = { +- UNIT_REQUIRED_BY, +- UNIT_REQUIRED_BY_OVERRIDABLE, +- UNIT_WANTED_BY, +- UNIT_BOUND_BY +- }; +- +- Unit *target; +- Iterator i; +- unsigned k; +- int r = 0; +- +- assert(u); +- +- for (k = 0; k < ELEMENTSOF(deps); k++) +- SET_FOREACH(target, u->dependencies[deps[k]], i) { +- r = unit_add_default_target_dependency(u, target); +- if (r < 0) +- return r; +- } +- +- return r; +-} +- + static int unit_add_slice_dependencies(Unit *u) { + assert(u); + +@@ -1217,10 +1206,7 @@ int unit_load(Unit *u) { + } + + if (u->load_state == UNIT_LOADED) { +- +- r = unit_add_target_dependencies(u); +- if (r < 0) +- goto fail; ++ unit_add_to_target_deps_queue(u); + + r = unit_add_slice_dependencies(u); + if (r < 0) +diff --git a/src/core/unit.h b/src/core/unit.h +index 480e2e95f..dfec9cea0 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -162,6 +162,9 @@ struct Unit { + /* CGroup realize members queue */ + LIST_FIELDS(Unit, cgroup_queue); + ++ /* Target dependencies queue */ ++ LIST_FIELDS(Unit, target_deps_queue); ++ + /* PIDs we keep an eye on. Note that a unit might have many + * more, but these are the ones we care enough about to + * process SIGCHLD for */ +@@ -228,6 +231,7 @@ struct Unit { + bool in_cleanup_queue:1; + bool in_gc_queue:1; + bool in_cgroup_queue:1; ++ bool in_target_deps_queue:1; + + bool sent_dbus_new_signal:1; + +@@ -498,6 +502,7 @@ void unit_add_to_load_queue(Unit *u); + void unit_add_to_dbus_queue(Unit *u); + void unit_add_to_cleanup_queue(Unit *u); + void unit_add_to_gc_queue(Unit *u); ++void unit_add_to_target_deps_queue(Unit *u); + + int unit_merge(Unit *u, Unit *other); + int unit_merge_by_name(Unit *u, const char *other); diff --git a/SOURCES/0649-man-correct-the-meaning-of-TimeoutStopSec.patch b/SOURCES/0649-man-correct-the-meaning-of-TimeoutStopSec.patch new file mode 100644 index 00000000..aa55434e --- /dev/null +++ b/SOURCES/0649-man-correct-the-meaning-of-TimeoutStopSec.patch @@ -0,0 +1,35 @@ +From 273a3d35df021128bd72e124d943cbb7b1c7194c Mon Sep 17 00:00:00 2001 +From: Jan Synacek +Date: Fri, 22 Jun 2018 09:11:49 +0200 +Subject: [PATCH] man: correct the meaning of TimeoutStopSec= + +Fixes: #9325 +(cherry picked from commit 9a6da355a06e2b272717f2ac23e41945ce56eb6d) +Resolves: #1305509 +--- + man/systemd.service.xml | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/man/systemd.service.xml b/man/systemd.service.xml +index a274db480..d147e449a 100644 +--- a/man/systemd.service.xml ++++ b/man/systemd.service.xml +@@ -429,12 +429,12 @@ + + + TimeoutStopSec= +- Configures the time to wait for stop. If a +- service is asked to stop, but does not terminate in the +- specified time, it will be terminated forcibly via +- SIGTERM, and after another timeout of +- equal duration with SIGKILL (see +- KillMode= in ++ This option serves two purposes. First, it configures the time to wait for each ++ ExecStop= command. If any of them times out, subsequent ExecStop= commands ++ are skipped and the service will be terminated by SIGTERM. If no ExecStop= ++ commands are specified, the service gets the SIGTERM immediately. Second, it configures the time ++ to wait for the service itself to stop. If it doesn't terminate in the specified time, it will be forcibly terminated ++ by SIGKILL (see KillMode= in + systemd.kill5). + Takes a unit-less value in seconds, or a time span value such + as "5min 20s". Pass 0 to disable the diff --git a/SOURCES/0650-rules-mark-hotplugged-memory-as-movable.patch b/SOURCES/0650-rules-mark-hotplugged-memory-as-movable.patch new file mode 100644 index 00000000..996c107d --- /dev/null +++ b/SOURCES/0650-rules-mark-hotplugged-memory-as-movable.patch @@ -0,0 +1,32 @@ +From 7431c551954ad63fe61cda18888e1e89419bd631 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 20 Jul 2018 09:48:04 +0200 +Subject: [PATCH] rules: mark hotplugged memory as movable + +Otherwise the kernel is free to use to memory block also for storing +non-movable memory (any other memory except anonymous memory allocations +and page cache). If user later wants to hot unplug the memory the kernel +will return error in case that some non-movable memory has been place to +the memory block. + +Marking hot plugged memory blocks as movable seems to be better +default. Users with specific needs are free to override this udev rule. + +Resolves: #1563532 +--- + rules/40-redhat.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules +index 34a1df9c4..26f726001 100644 +--- a/rules/40-redhat.rules ++++ b/rules/40-redhat.rules +@@ -4,7 +4,7 @@ + SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1" + + # Memory hotadd request +-SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online" ++SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online_movable" + + # reload sysctl.conf / sysctl.conf.d settings when the bridge module is loaded + ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/bridge" diff --git a/SOURCES/0651-udev-add-ID_INPUT_SWITCH-for-devices-with-switch-cap.patch b/SOURCES/0651-udev-add-ID_INPUT_SWITCH-for-devices-with-switch-cap.patch new file mode 100644 index 00000000..712b78fc --- /dev/null +++ b/SOURCES/0651-udev-add-ID_INPUT_SWITCH-for-devices-with-switch-cap.patch @@ -0,0 +1,27 @@ +From fa22d8e9697a0a896007998fdf2cabe7baf98bec Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +Date: Tue, 10 Jan 2017 17:36:46 +1000 +Subject: [PATCH] udev: add ID_INPUT_SWITCH for devices with switch capability + (#5057) + +(cherry picked from commit 64083a6078630372623bb1013a45d3bf31d8a836) + +Resolves: #1597240 +--- + src/udev/udev-builtin-input_id.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/src/udev/udev-builtin-input_id.c b/src/udev/udev-builtin-input_id.c +index 46f1c539d..d6ae07304 100644 +--- a/src/udev/udev-builtin-input_id.c ++++ b/src/udev/udev-builtin-input_id.c +@@ -250,6 +250,9 @@ static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], boo + get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); + test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, test); + test_key(dev, bitmask_ev, bitmask_key, test); ++ ++ if (test_bit(EV_SW, bitmask_ev)) ++ udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1"); + } + + devnode = udev_device_get_devnode(dev); diff --git a/SOURCES/0652-rules-disable-support-for-Dell-IR-cameras.patch b/SOURCES/0652-rules-disable-support-for-Dell-IR-cameras.patch new file mode 100644 index 00000000..f1348c2e --- /dev/null +++ b/SOURCES/0652-rules-disable-support-for-Dell-IR-cameras.patch @@ -0,0 +1,32 @@ +From e2a2326a283fe38463e637e34205c50ec3066424 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 18 Jul 2018 14:36:17 +0200 +Subject: [PATCH] rules: disable support for Dell IR cameras + +Resolves: #1591316 +--- + Makefile.am | 1 + + rules/40-redhat-disable-dell-ir-camera.rules | 2 ++ + 2 files changed, 3 insertions(+) + create mode 100644 rules/40-redhat-disable-dell-ir-camera.rules + +diff --git a/Makefile.am b/Makefile.am +index cbc120dad..40ebbe98e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3523,6 +3523,7 @@ dist_udevrules_DATA += \ + rules/95-udev-late.rules \ + rules/40-redhat.rules \ + rules/40-redhat-disable-lenovo-ir-camera.rules \ ++ rules/40-redhat-disable-dell-ir-camera.rules \ + rules/73-idrac.rules \ + rules/80-net-name-slot.rules + +diff --git a/rules/40-redhat-disable-dell-ir-camera.rules b/rules/40-redhat-disable-dell-ir-camera.rules +new file mode 100644 +index 000000000..2806482a5 +--- /dev/null ++++ b/rules/40-redhat-disable-dell-ir-camera.rules +@@ -0,0 +1,2 @@ ++# Disable known IR cameras in Dell Notebooks ++SUBSYSTEM=="usb", ATTRS{idVendor}=="0BDA", ATTRS{idProduct}=="58F6", ATTR{authorized}="0" diff --git a/SOURCES/0653-rpm-fix-systemd_user_post-macro.patch b/SOURCES/0653-rpm-fix-systemd_user_post-macro.patch new file mode 100644 index 00000000..0a2c82b5 --- /dev/null +++ b/SOURCES/0653-rpm-fix-systemd_user_post-macro.patch @@ -0,0 +1,36 @@ +From dda4324fa0b1fb1e07dea18585df6962d8f34b0f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tadej=20Jane=C5=BE?= +Date: Sun, 22 Nov 2015 20:38:05 +0100 +Subject: [PATCH] rpm: fix %systemd_user_post() macro. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Escape "--user" and "--global" arguments with "\\" since rpm treats +arguments starting with "-" as macro options which causes "Unknown +option" rpm error. +Use %{expand:...} to force expansion of the inner macro. Otherwise %{?*} +is recursively defined as "\--user \--global {%?*}" which causes +"Too many levels of recursion in macro expansion" rpm error. + +Thanks to Michael Mráka for helping me fix the above issues. + +(cherry picked from commit e67ba783696f21782ad5c2ba00515d387016e785) +Related: #1582383 +--- + src/core/macros.systemd.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in +index bea6ef1da..662791ccc 100644 +--- a/src/core/macros.systemd.in ++++ b/src/core/macros.systemd.in +@@ -43,7 +43,7 @@ if [ $1 -eq 1 ] ; then \ + fi \ + %{nil} + +-%systemd_user_post() %systemd_post --user --global %{?*} ++%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}} + + %systemd_preun() \ + if [ $1 -eq 0 ] ; then \ diff --git a/SOURCES/0654-rpm-remove-confusing-user-before-global.patch b/SOURCES/0654-rpm-remove-confusing-user-before-global.patch new file mode 100644 index 00000000..965083e7 --- /dev/null +++ b/SOURCES/0654-rpm-remove-confusing-user-before-global.patch @@ -0,0 +1,35 @@ +From 4bc18a925e964f10b4e7ed92e8e0d84bf985c6a8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Sat, 19 May 2018 13:01:55 +0200 +Subject: [PATCH] rpm: remove confusing --user before --global + +Fixes #9027. + +(cherry picked from commit 28d36da64a7a23a55e8d0a139f2620384fd058b3) +Resolves: #1582383 +--- + src/core/macros.systemd.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/macros.systemd.in b/src/core/macros.systemd.in +index 662791ccc..3d6e41274 100644 +--- a/src/core/macros.systemd.in ++++ b/src/core/macros.systemd.in +@@ -43,7 +43,7 @@ if [ $1 -eq 1 ] ; then \ + fi \ + %{nil} + +-%systemd_user_post() %{expand:%systemd_post \\--user \\--global %%{?*}} ++%systemd_user_post() %{expand:%systemd_post \\--global %%{?*}} + + %systemd_preun() \ + if [ $1 -eq 0 ] ; then \ +@@ -56,7 +56,7 @@ fi \ + %systemd_user_preun() \ + if [ $1 -eq 0 ] ; then \ + # Package removal, not upgrade \ +- systemctl --no-reload --user --global disable %{?*} > /dev/null 2>&1 || : \ ++ systemctl --global disable %{?*} > /dev/null 2>&1 || : \ + fi \ + %{nil} + diff --git a/SOURCES/0655-automount-handle-state-changes-of-the-corresponding-.patch b/SOURCES/0655-automount-handle-state-changes-of-the-corresponding-.patch new file mode 100644 index 00000000..f835f2f7 --- /dev/null +++ b/SOURCES/0655-automount-handle-state-changes-of-the-corresponding-.patch @@ -0,0 +1,58 @@ +From b4f506932592b991363b8be11e40b62f861bd032 Mon Sep 17 00:00:00 2001 +From: Michael Olbrich +Date: Fri, 24 Jul 2015 22:25:28 +0200 +Subject: [PATCH] automount: handle state changes of the corresponding mount + unit correctly + +The expire timeout must be started/stopped if the corresponding mount unit +changes its state, e.g. it is started via local-fs.target or stopped by a +manual umount. + +(cherry picked from commit 3dbadf9ef96e76f1bc472660ba5435dc0fa27a66) + +Resolves: #1596241 +--- + src/core/automount.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index 08519e49c..f57782b9b 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -499,6 +499,7 @@ static int automount_send_ready(Automount *a, Set *tokens, int status) { + + int automount_update_mount(Automount *a, MountState old_state, MountState state) { + _cleanup_close_ int ioctl_fd = -1; ++ int r; + + assert(a); + +@@ -506,6 +507,9 @@ int automount_update_mount(Automount *a, MountState old_state, MountState state) + case MOUNT_MOUNTED: + case MOUNT_REMOUNTING: + automount_send_ready(a, a->tokens, 0); ++ r = automount_start_expire(a); ++ if (r < 0) ++ log_unit_warning_errno(UNIT(a)->id, r, "Failed to start expiration timer, ignoring: %m"); + break; + case MOUNT_DEAD: + case MOUNT_UNMOUNTING: +@@ -518,6 +522,7 @@ int automount_update_mount(Automount *a, MountState old_state, MountState state) + case MOUNT_FAILED: + if (old_state != state) + automount_send_ready(a, a->tokens, -ENODEV); ++ (void) sd_event_source_set_enabled(a->expire_event_source, SD_EVENT_OFF); + break; + default: + break; +@@ -768,10 +773,6 @@ static void automount_enter_running(Automount *a) { + goto fail; + } + +- r = automount_start_expire(a); +- if (r < 0) +- log_unit_warning_errno(UNIT(a)->id, r, "Failed to start expiration timer, ignoring: %m"); +- + automount_set_state(a, AUTOMOUNT_RUNNING); + return; + diff --git a/SOURCES/0656-man-document-that-SIGCONT-always-follows-SIGTERM.patch b/SOURCES/0656-man-document-that-SIGCONT-always-follows-SIGTERM.patch new file mode 100644 index 00000000..a288f3b7 --- /dev/null +++ b/SOURCES/0656-man-document-that-SIGCONT-always-follows-SIGTERM.patch @@ -0,0 +1,32 @@ +From 210c9e5dd1e3d0e37a16225a63840d71b473684c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 15 Jun 2015 12:05:11 +0200 +Subject: [PATCH] man: document that SIGCONT always follows SIGTERM + +As requested in #199. + +(cherry picked from commit e8c53936316288ea3b33b5997b175862f0efef92) +Resolves: #1601794 +--- + man/systemd.kill.xml | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/man/systemd.kill.xml b/man/systemd.kill.xml +index e57f0e724..1292f4f51 100644 +--- a/man/systemd.kill.xml ++++ b/man/systemd.kill.xml +@@ -136,7 +136,13 @@ + by SIGKILL (see above and below). For a + list of valid signals, see + signal7. +- Defaults to SIGTERM. ++ Defaults to SIGTERM. ++ ++ Note that right after sending the signal specified in ++ this setting systemd will always send ++ SIGCONT, to ensure that even suspended ++ tasks can be terminated cleanly. ++ + + + diff --git a/SOURCES/0657-rules-add-udev-rule-that-automatically-offline-HW-at.patch b/SOURCES/0657-rules-add-udev-rule-that-automatically-offline-HW-at.patch new file mode 100644 index 00000000..fcef9bc1 --- /dev/null +++ b/SOURCES/0657-rules-add-udev-rule-that-automatically-offline-HW-at.patch @@ -0,0 +1,46 @@ +From 6bc676b1a1bfa7145106f737a6747526ce662b93 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Mon, 23 Jul 2018 16:57:22 +0200 +Subject: [PATCH] rules: add udev rule that automatically offline HW attached + to ACPI container + +Resolves: #1597958 +--- + Makefile.am | 1 + + rules/40-redhat-hotunplug.rules | 14 ++++++++++++++ + 2 files changed, 15 insertions(+) + create mode 100644 rules/40-redhat-hotunplug.rules + +diff --git a/Makefile.am b/Makefile.am +index 40ebbe98e..3995dcce8 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3524,6 +3524,7 @@ dist_udevrules_DATA += \ + rules/40-redhat.rules \ + rules/40-redhat-disable-lenovo-ir-camera.rules \ + rules/40-redhat-disable-dell-ir-camera.rules \ ++ rules/40-redhat-hotunplug.rules \ + rules/73-idrac.rules \ + rules/80-net-name-slot.rules + +diff --git a/rules/40-redhat-hotunplug.rules b/rules/40-redhat-hotunplug.rules +new file mode 100644 +index 000000000..3befdaffc +--- /dev/null ++++ b/rules/40-redhat-hotunplug.rules +@@ -0,0 +1,14 @@ ++# ACPI0004 container offline for Huawei Kunlun ++# do not edit this file, it will be overwritten on update ++ ++SUBSYSTEM=="container", ACTION=="change", DEVPATH=="*/ACPI0004:??", \ ++RUN+="/bin/sh -c ' \ ++if [ $(cat /sys/$env{DEVPATH}/online) -eq 1 ]; then \ ++ find -L /sys/$env{DEVPATH}/firmware_node/*/physical_node* -maxdepth 1 -name online | \ ++ while read line; do \ ++ if [ $(cat $line) -eq 1 ]; then \ ++ /bin/echo 0 > $line; \ ++ fi \ ++ done; \ ++ /bin/echo 0 > /sys/$env{DEVPATH}/online; \ ++fi'" +\ No newline at end of file diff --git a/SOURCES/0658-Revert-rules-mark-hotplugged-memory-as-movable.patch b/SOURCES/0658-Revert-rules-mark-hotplugged-memory-as-movable.patch new file mode 100644 index 00000000..264a428d --- /dev/null +++ b/SOURCES/0658-Revert-rules-mark-hotplugged-memory-as-movable.patch @@ -0,0 +1,25 @@ +From e1311df43e9c63e72b1a6b329f5ffc9bcd0f37e1 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 16 Aug 2018 08:38:31 +0000 +Subject: [PATCH] Revert "rules: mark hotplugged memory as movable" + +This reverts commit 7431c551954ad63fe61cda18888e1e89419bd631. + +Resolves: #1614686 +--- + rules/40-redhat.rules | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules +index 26f726001..34a1df9c4 100644 +--- a/rules/40-redhat.rules ++++ b/rules/40-redhat.rules +@@ -4,7 +4,7 @@ + SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1" + + # Memory hotadd request +-SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online_movable" ++SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online" + + # reload sysctl.conf / sysctl.conf.d settings when the bridge module is loaded + ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/bridge" diff --git a/SOURCES/0659-rules-implement-new-memory-hotplug-policy.patch b/SOURCES/0659-rules-implement-new-memory-hotplug-policy.patch new file mode 100644 index 00000000..250ce616 --- /dev/null +++ b/SOURCES/0659-rules-implement-new-memory-hotplug-policy.patch @@ -0,0 +1,49 @@ +From c50b7bcbebcfebfce3a7e7fb77f88f4b590fb2b5 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 16 Aug 2018 09:31:51 +0000 +Subject: [PATCH] rules: implement new memory hotplug policy + +Our new policy is based on following motivations (assumptions), + * we want to allow the system to use hotplugged memory + * we want memory ballon inflation to work as expected in VMs (going for small + to big in terms of memory footprint) + * we want to allow memory hotplug and memory hot-unplug on high-end + enterprise server (we assume that node0 will have sufficient memory + resources and marking all memory as movable shouldn't be a problem) + +Policy: + * nevert online memory on s390 (on both physical and z/VM) + * mark memory as "online_movable" on physical machines + * mark memory as "online" in VMs + +If you have the feeling that all this is very wrong and we shouldn't +encode complex policies in udev rules you are absolutely right. However, +for now, we don't have any better place where to put it. In ideal world +we would have a user-space daemon that would be able to configure the +system wrt. to currently present HW and user-defined policy. + +Resolves: #1614686 +--- + rules/40-redhat.rules | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/rules/40-redhat.rules b/rules/40-redhat.rules +index 34a1df9c4..1b10e173d 100644 +--- a/rules/40-redhat.rules ++++ b/rules/40-redhat.rules +@@ -4,7 +4,14 @@ + SUBSYSTEM=="cpu", ACTION=="add", TEST=="online", ATTR{online}=="0", ATTR{online}="1" + + # Memory hotadd request +-SUBSYSTEM=="memory", ACTION=="add", PROGRAM="/bin/uname -p", RESULT!="s390*", ATTR{state}=="offline", ATTR{state}="online" ++SUBSYSTEM!="memory", ACTION!="add", GOTO="memory_hotplug_end" ++PROGRAM="/bin/uname -p", RESULT=="s390*", GOTO="memory_hotplug_end" ++ ++ENV{.state}="online" ++PROGRAM="/bin/systemd-detect-virt", RESULT=="none", ENV{.state}="online_movable" ++ATTR{state}=="offline", ATTR{state}="$env{.state}" ++ ++LABEL="memory_hotplug_end" + + # reload sysctl.conf / sysctl.conf.d settings when the bridge module is loaded + ACTION=="add", SUBSYSTEM=="module", KERNEL=="bridge", RUN+="/usr/lib/systemd/systemd-sysctl --prefix=/proc/sys/net/bridge" diff --git a/SOURCES/0660-Revert-rules-add-udev-rule-that-automatically-offlin.patch b/SOURCES/0660-Revert-rules-add-udev-rule-that-automatically-offlin.patch new file mode 100644 index 00000000..26899fc1 --- /dev/null +++ b/SOURCES/0660-Revert-rules-add-udev-rule-that-automatically-offlin.patch @@ -0,0 +1,48 @@ +From 4b451af437d5d51b98d11d32130aac6938307798 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Fri, 17 Aug 2018 13:10:22 +0000 +Subject: [PATCH] Revert "rules: add udev rule that automatically offline HW + attached to ACPI container" + +This reverts commit 6bc676b1a1bfa7145106f737a6747526ce662b93. + +Related: #1597958 +--- + Makefile.am | 1 - + rules/40-redhat-hotunplug.rules | 14 -------------- + 2 files changed, 15 deletions(-) + delete mode 100644 rules/40-redhat-hotunplug.rules + +diff --git a/Makefile.am b/Makefile.am +index 3995dcce8..40ebbe98e 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3524,7 +3524,6 @@ dist_udevrules_DATA += \ + rules/40-redhat.rules \ + rules/40-redhat-disable-lenovo-ir-camera.rules \ + rules/40-redhat-disable-dell-ir-camera.rules \ +- rules/40-redhat-hotunplug.rules \ + rules/73-idrac.rules \ + rules/80-net-name-slot.rules + +diff --git a/rules/40-redhat-hotunplug.rules b/rules/40-redhat-hotunplug.rules +deleted file mode 100644 +index 3befdaffc..000000000 +--- a/rules/40-redhat-hotunplug.rules ++++ /dev/null +@@ -1,14 +0,0 @@ +-# ACPI0004 container offline for Huawei Kunlun +-# do not edit this file, it will be overwritten on update +- +-SUBSYSTEM=="container", ACTION=="change", DEVPATH=="*/ACPI0004:??", \ +-RUN+="/bin/sh -c ' \ +-if [ $(cat /sys/$env{DEVPATH}/online) -eq 1 ]; then \ +- find -L /sys/$env{DEVPATH}/firmware_node/*/physical_node* -maxdepth 1 -name online | \ +- while read line; do \ +- if [ $(cat $line) -eq 1 ]; then \ +- /bin/echo 0 > $line; \ +- fi \ +- done; \ +- /bin/echo 0 > /sys/$env{DEVPATH}/online; \ +-fi'" +\ No newline at end of file diff --git a/SOURCES/0661-cryptsetup-generator-introduce-basic-keydev-support.patch b/SOURCES/0661-cryptsetup-generator-introduce-basic-keydev-support.patch new file mode 100644 index 00000000..52f415a3 --- /dev/null +++ b/SOURCES/0661-cryptsetup-generator-introduce-basic-keydev-support.patch @@ -0,0 +1,258 @@ +From aafa651e44df825abeec061f295f227862aad6d9 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Thu, 30 Aug 2018 08:45:11 +0000 +Subject: [PATCH] cryptsetup-generator: introduce basic keydev support + +Dracut has a support for unlocking encrypted drives with keyfile stored +on the external drive. This support is included in the generated initrd +only if systemd module is not included. + +When systemd is used in initrd then attachment of encrypted drives is +handled by systemd-cryptsetup tools. Our generator has support for +keyfile, however, it didn't support keyfile on the external block +device (keydev). + +This commit introduces basic keydev support. Keydev can be specified per +luks.uuid on the kernel command line. Keydev is automatically mounted +during boot and we look for keyfile in the keydev +mountpoint (i.e. keyfile path is prefixed with the keydev mount point +path). After crypt device is attached we automatically unmount +where keyfile resides. + +Example: + rd.luks.key=70bc876b-f627-4038-9049-3080d79d2165=/key:LABEL=KEYDEV + +(cherry-picked from commit 70f5f48eb891b12e969577b464de61e15a2593da) + +Resolves: #1619743 +--- + man/systemd-cryptsetup-generator.xml | 14 ++++ + src/cryptsetup/cryptsetup-generator.c | 122 ++++++++++++++++++++++++++++++++-- + 2 files changed, 131 insertions(+), 5 deletions(-) + +diff --git a/man/systemd-cryptsetup-generator.xml b/man/systemd-cryptsetup-generator.xml +index b6270358e..8cfd8b6a8 100644 +--- a/man/systemd-cryptsetup-generator.xml ++++ b/man/systemd-cryptsetup-generator.xml +@@ -168,6 +168,20 @@ + to the one specified by rd.luks.key= or + luks.key= of the corresponding UUID, or the + password file that was specified without a UUID. ++ ++ It is also possible to specify an external device which ++ should be mounted before we attempt to unlock the LUKS device. ++ systemd-cryptsetup will use password file stored on that ++ device. Device containing password file is specified by ++ appending colon and a device identifier to the password file ++ path. For example, ++ rd.luks.uuid=b40f1abf-2a53-400a-889a-2eccc27eaa40 ++ rd.luks.key=b40f1abf-2a53-400a-889a-2eccc27eaa40=/keyfile:LABEL=keydev. ++ Hence, in this case, we will attempt to mount file system ++ residing on the block device with label keydev. ++ This syntax is for now only supported on a per-device basis, ++ i.e. you have to specify LUKS device UUID. ++ + rd.luks.key= + is honored only by initial RAM disk + (initrd) while +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 5f29093f5..42c30c5ca 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -38,6 +38,7 @@ + typedef struct crypto_device { + char *uuid; + char *keyfile; ++ char *keydev; + char *name; + char *options; + bool create; +@@ -51,14 +52,79 @@ static Hashmap *arg_disks = NULL; + static char *arg_default_options = NULL; + static char *arg_default_keyfile = NULL; + ++static int generate_keydev_mount(const char *name, const char *keydev, char **unit, char **mount) { ++ _cleanup_free_ char *u = NULL, *what = NULL, *where = NULL, *p = NULL; ++ _cleanup_fclose_ FILE *f = NULL; ++ int r; ++ ++ assert(name); ++ assert(keydev); ++ assert(unit); ++ assert(mount); ++ ++ r = mkdir_parents("/run/systemd/cryptsetup", 0755); ++ if (r < 0) ++ return r; ++ ++ r = mkdir("/run/systemd/cryptsetup", 0700); ++ if (r < 0) ++ return r; ++ ++ where = strjoin("/run/systemd/cryptsetup/keydev-", name, NULL); ++ if (!where) ++ return -ENOMEM; ++ ++ r = mkdir(where, 0700); ++ if (r < 0) ++ return r; ++ ++ u = unit_name_from_path(where, ".mount"); ++ if (!u) ++ return -ENOMEM; ++ ++ what = fstab_node_to_udev_node(keydev); ++ if (!what) ++ return -ENOMEM; ++ ++ p = strjoin(arg_dest, "/", u, NULL); ++ if (!p) ++ return log_oom(); ++ ++ f = fopen(p, "wxe"); ++ if (!f) ++ return log_error_errno(errno, "Failed to create unit file %s: %m", p); ++ ++ fprintf(f, ++ "# Automatically generated by systemd-cryptsetup-generator\n\n" ++ "[Unit]\n" ++ "DefaultDependencies=no\n\n" ++ "[Mount]\n" ++ "What=%s\n" ++ "Where=%s\n" ++ "Options=ro\n", what, where); ++ ++ r = fflush_and_check(f); ++ if (r < 0) ++ return r; ++ ++ *unit = u; ++ u = NULL; ++ ++ *mount = where; ++ where = NULL; ++ ++ return 0; ++} ++ + static int create_disk( + const char *name, + const char *device, ++ const char *keydev, + const char *password, + const char *options) { + + _cleanup_free_ char *p = NULL, *n = NULL, *d = NULL, *u = NULL, *to = NULL, *e = NULL, +- *filtered = NULL; ++ *filtered = NULL, *keydev_mount = NULL, *keyfile_path = NULL; + _cleanup_fclose_ FILE *f = NULL; + bool noauto, nofail, tmp, swap, netdev; + char *from; +@@ -98,6 +164,9 @@ static int create_disk( + if (!d) + return log_oom(); + ++ if (keydev && !password) ++ return log_error_errno(-EINVAL, "Keydev is specified, but path to the password file is missing: %m"); ++ + f = fopen(p, "wxe"); + if (!f) + return log_error_errno(errno, "Failed to create unit file %s: %m", p); +@@ -115,6 +184,20 @@ static int create_disk( + "After=%s\n", + netdev ? "remote-fs-pre.target" : "cryptsetup-pre.target"); + ++ if (keydev) { ++ _cleanup_free_ char *unit = NULL; ++ ++ r = generate_keydev_mount(name, keydev, &unit, &keydev_mount); ++ if (r < 0) ++ return log_error_errno(r, "Failed to generate keydev mount unit: %m"); ++ ++ keyfile_path = prefix_root(keydev_mount, password); ++ if (!keyfile_path) ++ return log_oom(); ++ ++ password = keyfile_path; ++ } ++ + if (!nofail) + fprintf(f, + "Before=%s\n", +@@ -181,6 +264,11 @@ static int create_disk( + "ExecStartPost=/sbin/mkswap '/dev/mapper/%s'\n", + name); + ++ if (keydev) ++ fprintf(f, ++ "ExecStartPost=/bin/umount '%s'\n\n", ++ keydev_mount); ++ + fflush(f); + if (ferror(f)) + return log_error_errno(errno, "Failed to write file %s: %m", p); +@@ -248,6 +336,7 @@ static void free_arg_disks(void) { + while ((d = hashmap_steal_first(arg_disks))) { + free(d->uuid); + free(d->keyfile); ++ free(d->keydev); + free(d->name); + free(d->options); + free(d); +@@ -335,13 +424,36 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { + + r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); + if (r == 2) { ++ char *c; ++ _cleanup_free_ char *keyfile = NULL, *keydev = NULL; ++ + d = get_crypto_device(uuid); + if (!d) + return log_oom(); + ++ c = strrchr(uuid_value, ':'); ++ if (!c) { ++ free(d->keyfile); ++ d->keyfile = uuid_value; ++ uuid_value = NULL; ++ ++ return 0; ++ } ++ ++ *c = '\0'; ++ keyfile = strdup(uuid_value); ++ keydev = strdup(++c); ++ ++ if (!keyfile || !keydev) ++ return log_oom(); ++ + free(d->keyfile); +- d->keyfile = uuid_value; +- uuid_value = NULL; ++ d->keyfile = keyfile; ++ keyfile = NULL; ++ ++ free(d->keydev); ++ d->keydev = keydev; ++ keydev = NULL; + } else if (free_and_strdup(&arg_default_keyfile, value)) + return log_oom(); + +@@ -420,7 +532,7 @@ static int add_crypttab_devices(void) { + continue; + } + +- r = create_disk(name, device, keyfile, (d && d->options) ? d->options : options); ++ r = create_disk(name, device, NULL, keyfile, (d && d->options) ? d->options : options); + if (r < 0) + return r; + +@@ -460,7 +572,7 @@ static int add_proc_cmdline_devices(void) { + else + options = "timeout=0"; + +- r = create_disk(d->name, device, d->keyfile ?: arg_default_keyfile, options); ++ r = create_disk(d->name, device, d->keydev, d->keyfile ?: arg_default_keyfile, options); + if (r < 0) + return r; + } diff --git a/SOURCES/0662-cryptsetup-generator-don-t-return-error-if-target-di.patch b/SOURCES/0662-cryptsetup-generator-don-t-return-error-if-target-di.patch new file mode 100644 index 00000000..22823951 --- /dev/null +++ b/SOURCES/0662-cryptsetup-generator-don-t-return-error-if-target-di.patch @@ -0,0 +1,38 @@ +From 8f47d483dc4e0510977c8868278148c476f58c17 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 4 Sep 2018 19:51:14 +0200 +Subject: [PATCH] cryptsetup-generator: don't return error if target directory + already exists + +Related: #1619743 +--- + src/cryptsetup/cryptsetup-generator.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index 42c30c5ca..a9598180c 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -63,11 +63,11 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un + assert(mount); + + r = mkdir_parents("/run/systemd/cryptsetup", 0755); +- if (r < 0) ++ if (r < 0 && r != -EEXIST) + return r; + + r = mkdir("/run/systemd/cryptsetup", 0700); +- if (r < 0) ++ if (r < 0 && errno != EEXIST) + return r; + + where = strjoin("/run/systemd/cryptsetup/keydev-", name, NULL); +@@ -75,7 +75,7 @@ static int generate_keydev_mount(const char *name, const char *keydev, char **un + return -ENOMEM; + + r = mkdir(where, 0700); +- if (r < 0) ++ if (r < 0 && errno != EEXIST) + return r; + + u = unit_name_from_path(where, ".mount"); diff --git a/SOURCES/0663-cryptsetup-generator-allow-whitespace-characters-in-.patch b/SOURCES/0663-cryptsetup-generator-allow-whitespace-characters-in-.patch new file mode 100644 index 00000000..0f312004 --- /dev/null +++ b/SOURCES/0663-cryptsetup-generator-allow-whitespace-characters-in-.patch @@ -0,0 +1,62 @@ +From afcf3919f5db85a00352a9937c9a5cb9c7b30269 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Tue, 4 Sep 2018 20:03:34 +0200 +Subject: [PATCH] cryptsetup-generator: allow whitespace characters in keydev + specification + +For example, =/keyfile:LABEL="KEYFILE FS" previously wouldn't +work, because we truncated label at the first whitespace character, +i.e. LABEL="KEYFILE". + +Related: #1619743 +--- + src/cryptsetup/cryptsetup-generator.c | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c +index a9598180c..7b90d2615 100644 +--- a/src/cryptsetup/cryptsetup-generator.c ++++ b/src/cryptsetup/cryptsetup-generator.c +@@ -421,27 +421,36 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { + return log_oom(); + + } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) { ++ int n; + +- r = sscanf(value, "%m[0-9a-fA-F-]=%ms", &uuid, &uuid_value); +- if (r == 2) { ++ r = sscanf(value, "%m[0-9a-fA-F-]=%n", &uuid, &n); ++ if (r == 1) { + char *c; ++ const char *keyspec; + _cleanup_free_ char *keyfile = NULL, *keydev = NULL; + + d = get_crypto_device(uuid); + if (!d) + return log_oom(); + +- c = strrchr(uuid_value, ':'); ++ keyspec = value + n; ++ ++ c = strrchr(keyspec, ':'); + if (!c) { ++ /* No keydev specified */ ++ keyfile = strdup(keyspec); ++ if (!keyfile) ++ return log_oom(); ++ + free(d->keyfile); +- d->keyfile = uuid_value; +- uuid_value = NULL; ++ d->keyfile = keyfile; ++ keyfile = NULL; + + return 0; + } + + *c = '\0'; +- keyfile = strdup(uuid_value); ++ keyfile = strdup(keyspec); + keydev = strdup(++c); + + if (!keyfile || !keydev) diff --git a/SOURCES/0664-Make-sure-the-mount-units-pulled-by-RequiresMountsFo.patch b/SOURCES/0664-Make-sure-the-mount-units-pulled-by-RequiresMountsFo.patch new file mode 100644 index 00000000..192052c9 --- /dev/null +++ b/SOURCES/0664-Make-sure-the-mount-units-pulled-by-RequiresMountsFo.patch @@ -0,0 +1,50 @@ +From d772781b2810ae71bace24cce05f255212a348ed Mon Sep 17 00:00:00 2001 +From: Franck Bui +Date: Thu, 8 Oct 2015 19:06:06 +0200 +Subject: [PATCH] Make sure the mount units pulled by 'RequiresMountsFor=' are + loaded (if they exist) + +We should make sure that mount units involved by 'RequiresMountsFor=' +directives are really loaded if not required by any others units so +that Requires= dependencies on the mount units are applied and thus +the mount unit dependencies are started. + +(cherry-picked from commit c7c89abb9edf9320246482bf4a8e0656199281ae) + +Resolves: #1619743 +--- + src/core/unit.c | 18 ++++++++++++++---- + 1 file changed, 14 insertions(+), 4 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index cfddce34d..e8532a057 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1131,13 +1131,23 @@ static int unit_add_mount_dependencies(Unit *u) { + char prefix[strlen(*i) + 1]; + + PATH_FOREACH_PREFIX_MORE(prefix, *i) { ++ _cleanup_free_ char *p = NULL; + Unit *m; + +- r = manager_get_unit_by_path(u->manager, prefix, ".mount", &m); +- if (r < 0) +- return r; +- if (r == 0) ++ p = unit_name_from_path(prefix, ".mount"); ++ if (!p) ++ return -ENOMEM; ++ ++ m = manager_get_unit(u->manager, p); ++ if (!m) { ++ /* Make sure to load the mount unit if ++ * it exists. If so the dependencies ++ * on this unit will be added later ++ * during the loading of the mount ++ * unit. */ ++ (void) manager_load_unit_prepare(u->manager, p, NULL, NULL, &m); + continue; ++ } + if (m == u) + continue; + diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index bb7cef5a..2e4d29c1 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -3,12 +3,11 @@ # directory. %global __requires_exclude pkg-config %global _hardened_build 1 -%global optflags %(echo %{optflags} | sed 's/-O3/-O2/') Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 219 -Release: 57%{?dist} +Release: 62%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: A System and Service Manager @@ -653,6 +652,57 @@ Patch0610: 0610-sd-journal-properly-handle-inotify-queue-overflow.patch Patch0611: 0611-sd-journal-make-sure-it-s-safe-to-call-sd_journal_pr.patch Patch0612: 0612-journalctl-Periodically-call-sd_journal_process-in-j.patch Patch0613: 0613-sd-journal-when-picking-up-a-new-file-compare-inode-.patch +Patch0614: 0614-tmpfiles-don-t-skip-cleanup-of-read-only-root-owned-.patch +Patch0615: 0615-timer-we-already-got-the-trigger-before-no-need-to-c.patch +Patch0616: 0616-doc-fix-links-to-binfmt_misc-kernel-documentation.patch +Patch0617: 0617-man-udevadm-remove-superfluous-version-from-subcomma.patch +Patch0618: 0618-man-udevadm-correctly-show-the-short-version-of-exit.patch +Patch0619: 0619-core-timer-downgrade-message-about-random-time-addit.patch +Patch0620: 0620-fd-util-add-new-acquire_data_fd-API-helper.patch +Patch0621: 0621-systemd-analyze-make-dump-work-for-large-of-units.patch +Patch0622: 0622-use-max.-message-size-allowed-by-DBus-spec-8936.patch +Patch0623: 0623-cryptsetup-support-LUKS2-on-disk-format.patch +Patch0624: 0624-core-scope-fix-missing-fragment_path.patch +Patch0625: 0625-units-don-t-put-udev-to-its-own-mount-namespace-with.patch +Patch0626: 0626-rules-disable-support-for-Lenovo-IR-cameras.patch +Patch0627: 0627-core-make-sure-systemctl-reload-or-try-restart-is-ac.patch +Patch0628: 0628-core-fix-confusing-logging-of-instantaneous-jobs.patch +Patch0629: 0629-core-correct-return-value-from-reload-methods.patch +Patch0630: 0630-core-always-try-harder-to-get-unit-status-message-fo.patch +Patch0631: 0631-core-unit_get_status_message_format-never-returns-NU.patch +Patch0632: 0632-core-try-harder-to-get-job-completion-messages-too.patch +Patch0633: 0633-core-remove-generic-job-completion-messages-from-uni.patch +Patch0634: 0634-core-do-not-log-done-failed-condition-jobs-as-if-uni.patch +Patch0635: 0635-core-log-completion-of-remaining-job-types.patch +Patch0636: 0636-core-adjust-job-completion-message-log-levels.patch +Patch0637: 0637-mount-add-new-LazyUnmount-setting-for-mount-units-ma.patch +Patch0638: 0638-rules-Add-MODEL_ID-for-NVMe-device-7037.patch +Patch0639: 0639-umount-always-use-MNT_FORCE-in-umount_all-7213.patch +Patch0640: 0640-core-Implement-timeout-based-umount-remount-limit.patch +Patch0641: 0641-core-Implement-sync_with_progress.patch +Patch0642: 0642-journal-fix-HMAC-calculation-when-appending-a-data-o.patch +Patch0643: 0643-journal-forward-messages-from-dev-log-unmodified-to-.patch +Patch0644: 0644-tmpfiles-use-safe_glob.patch +Patch0645: 0645-Fix-SELinux-labels-in-cgroup-filesystem-root-directo.patch +Patch0646: 0646-core-dont-t-remount-sys-fs-cgroup-for-relabel-if-not.patch +Patch0647: 0647-fix-race-between-daemon-reload-and-other-commands.patch +Patch0648: 0648-core-delay-adding-target-dependencies-until-all-unit.patch +Patch0649: 0649-man-correct-the-meaning-of-TimeoutStopSec.patch +Patch0650: 0650-rules-mark-hotplugged-memory-as-movable.patch +Patch0651: 0651-udev-add-ID_INPUT_SWITCH-for-devices-with-switch-cap.patch +Patch0652: 0652-rules-disable-support-for-Dell-IR-cameras.patch +Patch0653: 0653-rpm-fix-systemd_user_post-macro.patch +Patch0654: 0654-rpm-remove-confusing-user-before-global.patch +Patch0655: 0655-automount-handle-state-changes-of-the-corresponding-.patch +Patch0656: 0656-man-document-that-SIGCONT-always-follows-SIGTERM.patch +Patch0657: 0657-rules-add-udev-rule-that-automatically-offline-HW-at.patch +Patch0658: 0658-Revert-rules-mark-hotplugged-memory-as-movable.patch +Patch0659: 0659-rules-implement-new-memory-hotplug-policy.patch +Patch0660: 0660-Revert-rules-add-udev-rule-that-automatically-offlin.patch +Patch0661: 0661-cryptsetup-generator-introduce-basic-keydev-support.patch +Patch0662: 0662-cryptsetup-generator-don-t-return-error-if-target-di.patch +Patch0663: 0663-cryptsetup-generator-allow-whitespace-characters-in-.patch +Patch0664: 0664-Make-sure-the-mount-units-pulled-by-RequiresMountsFo.patch %global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);} @@ -705,7 +755,7 @@ Requires(pre): /usr/sbin/groupadd Requires: dbus Requires: %{name}-libs = %{version}-%{release} Requires: kmod >= 18-4 -Requires: powerel-release >= 7 +Requires: redhat-release >= 7.0 Requires: diffutils Provides: /bin/systemctl @@ -1050,6 +1100,9 @@ systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd- systemd-machine-id-setup >/dev/null 2>&1 || : /usr/lib/systemd/systemd-random-seed save >/dev/null 2>&1 || : systemctl daemon-reexec >/dev/null 2>&1 || : +for u in `systemctl show -p Id --state=active \*.automount | cut -d = -f 2`; do + systemctl try-restart $u >/dev/null 2>&1 || : +done systemctl start systemd-udevd.service >/dev/null 2>&1 || : udevadm hwdb --update >/dev/null 2>&1 || : journalctl --update-catalog >/dev/null 2>&1 || : @@ -1367,7 +1420,7 @@ fi %ghost %dir %{_localstatedir}/lib/systemd/coredump %ghost %dir %{_localstatedir}/lib/systemd/backlight %ghost %dir %{_localstatedir}/lib/systemd/rfkill -%ghost %{_localstatedir}/lib/systemd/random-seed +%ghost %attr(0600, root, root) %{_localstatedir}/lib/systemd/random-seed %ghost %{_localstatedir}/lib/systemd/clock %ghost %{_localstatedir}/lib/systemd/catalog/database %ghost %attr(0664,root,utmp) %{_localstatedir}/run/utmp @@ -1390,7 +1443,7 @@ fi %config(noreplace) %{_sysconfdir}/rsyslog.d/listen.conf %config(noreplace) %{_sysconfdir}/yum/protected.d/systemd.conf %config(noreplace) %{_sysconfdir}/pam.d/systemd-user -%ghost %{_sysconfdir}/udev/hwdb.bin +%ghost %attr(0444, root, root) %{_sysconfdir}/udev/hwdb.bin %{_rpmconfigdir}/macros.d/macros.systemd %{_sysconfdir}/xdg/systemd %{_sysconfdir}/rc.d/init.d/README @@ -1398,7 +1451,7 @@ fi %ghost %config(noreplace) %{_sysconfdir}/localtime %ghost %config(noreplace) %{_sysconfdir}/vconsole.conf %ghost %config(noreplace) %{_sysconfdir}/locale.conf -%ghost %config(noreplace) %{_sysconfdir}/machine-id +%ghost %attr(0444, root, root) %config(noreplace) %{_sysconfdir}/machine-id %ghost %config(noreplace) %{_sysconfdir}/machine-info %dir %{_sysconfdir}/X11/xorg.conf.d %ghost %config(noreplace) %{_sysconfdir}/X11/xorg.conf.d/00-keyboard.conf @@ -1626,6 +1679,63 @@ fi %{_mandir}/man8/systemd-resolved.* %changelog +* Fri Sep 07 2018 Lukas Nykryn - 219-62 +- cryptsetup-generator: introduce basic keydev support (#1619743) +- cryptsetup-generator: don't return error if target directory already exists (#1619743) +- cryptsetup-generator: allow whitespace characters in keydev specification (#1619743) +- Make sure the mount units pulled by 'RequiresMountsFor=' are loaded (if they exist) (#1619743) + +* Fri Aug 31 2018 Lukas Nykryn - 219-61 +- restart automounts unit on update (#1596241) + +* Fri Aug 17 2018 Lukas Nykryn - 219-60 +- Revert "rules: mark hotplugged memory as movable" (#1614686) +- rules: implement new memory hotplug policy (#1614686) +- Revert "rules: add udev rule that automatically offline HW attached to ACPI container" (#1597958) + +* Wed Jul 25 2018 Lukas Nykryn - 219-59 +- man: correct the meaning of TimeoutStopSec= (#1305509) +- rules: mark hotplugged memory as movable (#1563532) +- udev: add ID_INPUT_SWITCH for devices with switch capability (#5057) (#1597240) +- rules: disable support for Dell IR cameras (#1591316) +- rpm: fix %systemd_user_post() macro. (#1582383) +- rpm: remove confusing --user before --global (#1582383) +- automount: handle state changes of the corresponding mount unit correctly (#1596241) +- man: document that SIGCONT always follows SIGTERM (#1601794) +- rules: add udev rule that automatically offline HW attached to ACPI container (#1597958) + +* Thu Jun 21 2018 Lukas Nykryn - 219-58 +- tmpfiles: don't skip cleanup of read-only root owned files if TMPFILES_AGE_ALL is set (#1533638) +- timer: we already got the trigger before, no need to call UNIT_TRIGGER again (#1549119) +- doc: fix links to binfmt_misc kernel documentation (#1572244) +- man/udevadm: remove superfluous --version from subcommand (#1553076) +- man/udevadm: correctly show the short version of --exit (#1552712) +- core/timer: downgrade message about random time addition (#5229) (#1587906) +- fd-util: add new acquire_data_fd() API helper (#1446095) +- systemd-analyze: make dump work for large # of units (#1446095) +- use max. message size allowed by DBus spec (#8936) (#1446095) +- cryptsetup: support LUKS2 on-disk format (#1573838) +- units: don't put udev to its own mount namespace with slave propagation (#1432211) +- rules: disable support for Lenovo IR cameras (#1540418) +- core: make sure "systemctl reload-or-try-restart is actually a noop if a unit is not running (#1191920) +- core: fix confusing logging of instantaneous jobs (#1506256) +- core: correct return value from reload methods (#1506256) +- core: always try harder to get unit status message format string (#1506256) +- core: unit_get_status_message_format() never returns NULL (#1506256) +- core: try harder to get job completion messages too (#1506256) +- core: remove generic job completion messages from unit vtables (#1506256) +- core: do not log done failed-condition jobs as if unit started (#1506256) +- core: log completion of remaining job types (#1506256) +- core: adjust job completion message log levels (#1506256) +- mount: add new LazyUnmount= setting for mount units, mapping to umount(8)'s "-l" switch (#3827) (#1497264) +- rules: Add MODEL_ID for NVMe device (#7037) (#1397264) +- umount: always use MNT_FORCE in umount_all() (#7213) (#1571098) +- core: Implement timeout based umount/remount limit (#1571098) +- core: Implement sync_with_progress() (#1571098) +- journal: forward messages from /dev/log unmodified to syslog.socket (#1409659) +- tmpfiles: use safe_glob() (#1436004) +- core: delay adding target dependencies until all units are loaded and aliases resolved (#8381) (#1368856) + * Tue Feb 20 2018 Lukas Nykryn - 219-57 - sd-journal: properly handle inotify queue overflow (#1540538) - sd-journal: make sure it's safe to call sd_journal_process() before the first sd_journal_wait() (#1540538)