From 505ca81019a5640e15eaeb3bb165c0166ec27b3a Mon Sep 17 00:00:00 2001 From: Anita Zhang Date: Feb 19 2021 08:24:56 +0000 Subject: new release 247.3-1 Closely tracks the latest Fedora changes up to 247.3. The primary difference is that networkd and the standalone binaries are not split out into their own subpackages. Didn't seem worthwhile to split out networkd for a couple of MB and deal with the configuration changes related to missing the service files installed. I excluded the standalone binary subpackage since it's intended for non-systemd systems. --- diff --git a/.systemd.metadata b/.systemd.metadata index 9237e09..aef1460 100644 --- a/.systemd.metadata +++ b/.systemd.metadata @@ -1 +1 @@ -886c84cfa6861e1b367659b594722737d43d0fde SOURCES/systemd-246.1.tar.gz +9bad8622d0198406e6570ca7c54de0eac47e468e SOURCES/systemd-247.3.tar.gz diff --git a/SOURCES/0001-Do-not-assert-in-test_add_acls_for_user.patch b/SOURCES/0001-Do-not-assert-in-test_add_acls_for_user.patch deleted file mode 100644 index c13413c..0000000 --- a/SOURCES/0001-Do-not-assert-in-test_add_acls_for_user.patch +++ /dev/null @@ -1,42 +0,0 @@ -From b177b0ef92d226a9f303aecbff0cf2e7293667b3 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Sat, 8 Aug 2020 09:21:37 +0200 -Subject: [PATCH] Do not assert in test_add_acls_for_user() - -This is failing on s390x with: -/* test_add_acls_for_user */ -add_acls_for_user(3, 1000): Invalid argument -Assertion 'r >= 0' failed at src/test/test-acl-util.c:46, function test_add_acls_for_user(). Aborting. ---- - src/test/test-acl-util.c | 4 ---- - 1 file changed, 4 deletions(-) - -diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c -index 9f0e594e67..a91d64ab0c 100644 ---- a/src/test/test-acl-util.c -+++ b/src/test/test-acl-util.c -@@ -43,24 +43,20 @@ static void test_add_acls_for_user(void) { - - r = add_acls_for_user(fd, uid); - log_info_errno(r, "add_acls_for_user(%d, "UID_FMT"): %m", fd, uid); -- assert_se(r >= 0); - - cmd = strjoina("ls -l ", fn); - assert_se(system(cmd) == 0); - - cmd = strjoina("getfacl -p ", fn); -- assert_se(system(cmd) == 0); - - /* set the acls again */ - - r = add_acls_for_user(fd, uid); -- assert_se(r >= 0); - - cmd = strjoina("ls -l ", fn); - assert_se(system(cmd) == 0); - - cmd = strjoina("getfacl -p ", fn); -- assert_se(system(cmd) == 0); - - unlink(fn); - } diff --git a/SOURCES/0001-Revert-test-path-increase-timeout.patch b/SOURCES/0001-Revert-test-path-increase-timeout.patch deleted file mode 100644 index a9c226f..0000000 --- a/SOURCES/0001-Revert-test-path-increase-timeout.patch +++ /dev/null @@ -1,30 +0,0 @@ -From a73d30081a13eaeffce87f997726a179ec44d817 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Fri, 31 Jul 2020 10:50:37 +0200 -Subject: [PATCH 1/2] Revert "test-path: increase timeout" - -This partially reverts commit 500727c220354b81b68ed6667d9a6f0fafe3ba19. - -I was confused by the error message: the test says it timed out, but that's -because it's waiting for a failed unit to come back to life. There is no actual -timeout. - -So let's keep the minor refactoring that was done, but revert to the old short -timeout. ---- - src/test/test-path.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/test/test-path.c b/src/test/test-path.c -index 1075f31bc6..63b709c8da 100644 ---- a/src/test/test-path.c -+++ b/src/test/test-path.c -@@ -82,7 +82,7 @@ static void check_states(Manager *m, Path *path, Service *service, PathState pat - assert_se(m); - assert_se(service); - -- usec_t end = now(CLOCK_MONOTONIC) + 30 * USEC_PER_SEC; -+ usec_t end = now(CLOCK_MONOTONIC) + 2 * USEC_PER_SEC; - - while (path->result != PATH_SUCCESS || service->result != SERVICE_SUCCESS || - path->state != path_state || service->state != service_state) { diff --git a/SOURCES/0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch b/SOURCES/0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch deleted file mode 100644 index ed3536b..0000000 --- a/SOURCES/0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch +++ /dev/null @@ -1,427 +0,0 @@ -From a1ff72565c2f12b644a081ebbe3492f93ceb3bd5 Mon Sep 17 00:00:00 2001 -From: Chris Down -Date: Thu, 29 Oct 2020 12:03:52 +0000 -Subject: [PATCH 1/3] bpf: pid1: Pin reference to BPF programs for - post-coldplug -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -During `daemon-reload` and `daemon-reexec`, we detach and reattach all -BPF programs attached to cgroups. This, however, poses a real practical -problem for DevicePolicy (and some other settings using BPF): it -presents a period of time where the old device filtering BPF program has -been unloaded, but the new one has not been loaded yet. - -Since the filtering is at open() time, it has become apparent that that -there's a non-trivial period where applications inside that ostensibly -filtered cgroup can grab any device -- and often do so -- and then -retain access to that device even after the reload is over. Due to the -file continuing to be available after the initial open(), this issue is -particularly visible for DevicePolicy={strict,closed}, however it also -applies to other BPF programs we install. - -In particular, for BPF ingress/egress filtering this may have more -concerning implications: network traffic which is supposed to be -filtered will -- for a very brief period of time -- not be filtered or -subject to any restrictions imposed by BPF. - -These BPF programs are fundamentally attached to a cgroup lifetime, not -our unit lifetime, so it's enough to pin these programs by taking a -reference to affected BPF programs before reload/reexec. We can then -serialise the program's kernel-facing FD and cgroup attachment FD for -the new daemon, and have the daemon on the other side unpin the programs -after it's finished with coldplug. - -That means that, for example, the BPF program lifecycle during -daemon-reload or daemon-reexec changes from this: - - manager_clear_jobs_and_units - │ - ╔══════╪═════════╤═══════╗ - ║ prog │ no prog │ prog' ║ - ╚══════╧═════════╪═══════╝ - │ - manager_coldplug - -to this: - - manager_clear_jobs_and_units manager_dispatch_cgroup_realize_queue - │ │ - ╔══════╪═══════════════╤═══════════════════════╪═══════╗ - ║ prog │ prog (orphan) │ prog (orphan) + prog' │ prog' ║ - ╚══════╧═══════════════╪═══════════════════════╧═══════╝ - │ - manager_coldplug - -For daemon-reexec the semantics are mostly the same, but the point at -which the program becomes orphan is tied to the process lifecycle -instead. - -None of the BPF programs we install require exclusive access, so having -multiple instances of them running at the same time is fine. Custom -programs, of course, are unknown, but it's hard to imagine legitimate -cases which should be affected, whereas the benefits of this "overlap" -approach with reference pinning is immediately tangible. - -[keszybz: use _cleanup_ for unpin, use FOREACH_POINTER] ---- - src/core/bpf-firewall.c | 9 +-- - src/core/main.c | 9 +++ - src/core/manager.c | 163 ++++++++++++++++++++++++++++++++++++++- - src/core/manager.h | 6 ++ - src/shared/bpf-program.c | 10 +++ - src/shared/bpf-program.h | 1 + - 6 files changed, 191 insertions(+), 7 deletions(-) - -diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c -index bceb049b58..e3089ff6f4 100644 ---- a/src/core/bpf-firewall.c -+++ b/src/core/bpf-firewall.c -@@ -703,8 +703,7 @@ int bpf_firewall_install(Unit *u) { - if (r < 0) - return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m"); - -- flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI && -- (u->type == UNIT_SLICE || unit_cgroup_delegate(u))) ? BPF_F_ALLOW_MULTI : 0; -+ flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI) ? BPF_F_ALLOW_MULTI : 0; - - /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program, to - * minimize the time window when we don't account for IP traffic. */ -@@ -712,8 +711,7 @@ int bpf_firewall_install(Unit *u) { - u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed); - - if (u->ip_bpf_egress) { -- r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, -- flags | (set_isempty(u->ip_bpf_custom_egress) ? 0 : BPF_F_ALLOW_MULTI)); -+ r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags); - if (r < 0) - return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path); - -@@ -722,8 +720,7 @@ int bpf_firewall_install(Unit *u) { - } - - if (u->ip_bpf_ingress) { -- r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, -- flags | (set_isempty(u->ip_bpf_custom_ingress) ? 0 : BPF_F_ALLOW_MULTI)); -+ r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags); - if (r < 0) - return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path); - -diff --git a/src/core/main.c b/src/core/main.c -index 4a376976e9..9873f35f5e 100644 ---- a/src/core/main.c -+++ b/src/core/main.c -@@ -1144,6 +1144,14 @@ static int prepare_reexecute( - if (!fds) - return log_oom(); - -+ /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF -+ * program is active during task execution within a cgroup. This would be bad since this may have -+ * security or reliability implications: devices we should filter won't be filtered, network activity -+ * we should filter won't be filtered, etc. We pin all the existing devices by bumping their -+ * refcount, and then storing them to later have it decremented. */ -+ _cleanup_(manager_unpin_all_cgroup_bpf_programsp) Manager *m_unpin = -+ manager_pin_all_cgroup_bpf_programs(m); -+ - r = manager_serialize(m, f, fds, switching_root); - if (r < 0) - return r; -@@ -1159,6 +1167,7 @@ static int prepare_reexecute( - if (r < 0) - return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); - -+ TAKE_PTR(m_unpin); - *ret_f = TAKE_PTR(f); - *ret_fds = TAKE_PTR(fds); - -diff --git a/src/core/manager.c b/src/core/manager.c -index 41e0d73736..1ce0e05706 100644 ---- a/src/core/manager.c -+++ b/src/core/manager.c -@@ -64,6 +64,7 @@ - #include "rlimit-util.h" - #include "rm-rf.h" - #include "serialize.h" -+#include "set.h" - #include "signal-util.h" - #include "socket-util.h" - #include "special.h" -@@ -3210,6 +3211,79 @@ static void manager_serialize_gid_refs(Manager *m, FILE *f) { - manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); - } - -+static int serialize_limbo_bpf_program(FILE *f, FDSet *fds, BPFProgram *p) { -+ int copy; -+ _cleanup_free_ char *ap = NULL; -+ -+ /* We don't actually need the instructions or other data, since this is only used on the other side -+ * for BPF limbo, which just requires the program type, cgroup path, and kernel-facing BPF file -+ * descriptor. We don't even need to know what unit or directive it's attached to, since we're just -+ * going to expire it after coldplug. */ -+ -+ assert(f); -+ assert(p); -+ -+ /* If the program isn't attached to the kernel yet, there's no reason to serialise it for limbo. Just -+ * let it be skeletonized and then coldplug can do the work on the other side if it's still -+ * necessary. */ -+ if (p->kernel_fd < 0 || !p->attached_path) -+ return -ENOTCONN; -+ -+ copy = fdset_put_dup(fds, p->kernel_fd); -+ if (copy < 0) -+ return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m"); -+ -+ /* Otherwise, on daemon-reload, we'd remain pinned. */ -+ safe_close(p->kernel_fd); -+ -+ ap = cescape(p->attached_path); -+ if (!ap) -+ return log_oom(); -+ -+ return serialize_item_format(f, "bpf-limbo", "%i %i %i \"%s\"", -+ copy, p->prog_type, p->attached_type, ap); -+} -+ -+static void deserialize_limbo_bpf_program(Manager *m, FDSet *fds, const char *value) { -+ _cleanup_free_ char *raw_fd = NULL, *raw_pt = NULL, *raw_at = NULL, *cgpath = NULL; -+ int fd, r, prog_type, attached_type; -+ -+ assert(m); -+ assert(value); -+ -+ r = extract_first_word(&value, &raw_fd, NULL, 0); -+ if (r <= 0 || safe_atoi(raw_fd, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) -+ return (void) log_error("Failed to parse bpf-limbo FD: %s", value); -+ -+ r = extract_first_word(&value, &raw_pt, NULL, 0); -+ if (r <= 0 || safe_atoi(raw_pt, &prog_type) < 0) -+ return (void) log_error("Failed to parse bpf-limbo program type: %s", value); -+ -+ r = extract_first_word(&value, &raw_at, NULL, 0); -+ if (r <= 0 || safe_atoi(raw_at, &attached_type) < 0) -+ return (void) log_error("Failed to parse bpf-limbo attached type: %s", value); -+ -+ r = extract_first_word(&value, &cgpath, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE); -+ if (r <= 0) -+ return (void) log_error("Failed to parse attached path for BPF limbo FD %s", value); -+ -+ _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL; -+ r = bpf_program_new(prog_type, &p); -+ if (r < 0) -+ return (void) log_error_errno(r, "Failed to create BPF limbo program: %m"); -+ -+ /* Just enough to free it when the time is right, this does not have enough information be used as a -+ * real BPFProgram. */ -+ p->attached_type = attached_type; -+ p->kernel_fd = fdset_remove(fds, fd); -+ p->attached_path = TAKE_PTR(cgpath); -+ -+ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); -+ if (r < 0) -+ return (void) log_error_errno(r, "Failed to register BPF limbo program for FD %s: %m", value); -+ TAKE_PTR(p); -+} -+ - int manager_serialize( - Manager *m, - FILE *f, -@@ -3221,6 +3295,7 @@ int manager_serialize( - Iterator i; - Unit *u; - int r; -+ BPFProgram *p; - - assert(m); - assert(f); -@@ -3265,6 +3340,9 @@ int manager_serialize( - (void) serialize_dual_timestamp(f, joined, m->timestamps + q); - } - -+ SET_FOREACH(p, m->bpf_limbo_progs, i) -+ (void) serialize_limbo_bpf_program(f, fds, p); -+ - if (!switching_root) - (void) serialize_strv(f, "env", m->client_environment); - -@@ -3543,7 +3621,10 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { - else - m->n_failed_jobs += n; - -- } else if ((val = startswith(l, "taint-usr="))) { -+ } else if ((val = startswith(l, "bpf-limbo="))) -+ deserialize_limbo_bpf_program(m, fds, val); -+ -+ else if ((val = startswith(l, "taint-usr="))) { - int b; - - b = parse_boolean(val); -@@ -3719,6 +3800,67 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { - return manager_deserialize_units(m, f, fds); - } - -+Manager* manager_pin_all_cgroup_bpf_programs(Manager *m) { -+ int r; -+ Unit *u; -+ Iterator ih, is; -+ -+ assert(m); -+ -+ HASHMAP_FOREACH(u, m->units, ih) { -+ BPFProgram *p; -+ -+ FOREACH_POINTER(p, -+ u->bpf_device_control_installed, -+ u->ip_bpf_ingress, -+ u->ip_bpf_ingress_installed, -+ u->ip_bpf_egress, -+ u->ip_bpf_egress_installed) -+ if (p) { -+ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); -+ if (r < 0) { -+ log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m"); -+ continue; -+ } -+ -+ bpf_program_ref(p); -+ } -+ -+ Set *s; -+ FOREACH_POINTER(s, -+ u->ip_bpf_custom_ingress, -+ u->ip_bpf_custom_ingress_installed, -+ u->ip_bpf_custom_egress, -+ u->ip_bpf_custom_egress_installed) -+ SET_FOREACH(p, s, is) { -+ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); -+ if (r < 0) { -+ log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m"); -+ continue; -+ } -+ -+ bpf_program_ref(p); -+ } -+ } -+ -+ log_debug("Pinned %d BPF programs", set_size(m->bpf_limbo_progs)); -+ -+ return m; -+} -+ -+static void manager_skeletonize_all_cgroup_bpf_programs(Manager *m) { -+ BPFProgram *p; -+ Iterator i; -+ -+ SET_FOREACH(p, m->bpf_limbo_progs, i) -+ bpf_program_skeletonize(p); -+} -+ -+void manager_unpin_all_cgroup_bpf_programs(Manager *m) { -+ log_debug("Unpinning %d BPF programs", set_size(m->bpf_limbo_progs)); -+ set_clear_with_destructor(m->bpf_limbo_progs, bpf_program_unref); -+} -+ - int manager_reload(Manager *m) { - _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; - _cleanup_fdset_free_ FDSet *fds = NULL; -@@ -3738,6 +3880,13 @@ int manager_reload(Manager *m) { - /* We are officially in reload mode from here on. */ - reloading = manager_reloading_start(m); - -+ /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF -+ * program is active during task execution within a cgroup. This would be bad since this may have -+ * security or reliability implications: devices we should filter won't be filtered, network activity -+ * we should filter won't be filtered, etc. We pin all the existing devices by bumping their -+ * refcount, and then storing them to later have it decremented. */ -+ (void) manager_pin_all_cgroup_bpf_programs(m); -+ - r = manager_serialize(m, f, fds, false); - if (r < 0) - return r; -@@ -3762,6 +3911,12 @@ int manager_reload(Manager *m) { - m->uid_refs = hashmap_free(m->uid_refs); - m->gid_refs = hashmap_free(m->gid_refs); - -+ /* The only canonical reference left to the dynamically allocated parts of these BPF programs is -+ * going to be on the other side of manager_deserialize, so the freeable parts can now be freed. The -+ * program itself will be detached as part of manager_vacuum. */ -+ manager_skeletonize_all_cgroup_bpf_programs(m); -+ m->bpf_limbo_progs = set_free(m->bpf_limbo_progs); -+ - r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); - if (r < 0) - log_warning_errno(r, "Failed to initialize path lookup table, ignoring: %m"); -@@ -4700,6 +4855,12 @@ static void manager_vacuum(Manager *m) { - - /* Release any runtimes no longer referenced */ - exec_runtime_vacuum(m); -+ -+ /* Release any outmoded BPF programs that were deserialized from the previous manager, since new ones -+ * should be in action now. We first need to make sure all entries in the cgroup realize queue are -+ * complete, otherwise BPF firewalls/etc may not have been set up yet. */ -+ (void) manager_dispatch_cgroup_realize_queue(m); -+ manager_unpin_all_cgroup_bpf_programs(m); - } - - int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { -diff --git a/src/core/manager.h b/src/core/manager.h -index 81b0c13a95..6f8f8b04b4 100644 ---- a/src/core/manager.h -+++ b/src/core/manager.h -@@ -433,6 +433,8 @@ struct Manager { - bool honor_device_enumeration; - - VarlinkServer *varlink_server; -+ -+ Set *bpf_limbo_progs; - }; - - static inline usec_t manager_default_timeout_abort_usec(Manager *m) { -@@ -474,6 +476,10 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode - int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret); - int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e); - -+Manager* manager_pin_all_cgroup_bpf_programs(Manager *m); -+void manager_unpin_all_cgroup_bpf_programs(Manager *m); -+DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unpin_all_cgroup_bpf_programs); -+ - void manager_dump_units(Manager *s, FILE *f, const char *prefix); - void manager_dump_jobs(Manager *s, FILE *f, const char *prefix); - void manager_dump(Manager *s, FILE *f, const char *prefix); -diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c -index e5c9df4004..cc479aa52e 100644 ---- a/src/shared/bpf-program.c -+++ b/src/shared/bpf-program.c -@@ -210,6 +210,16 @@ int bpf_program_cgroup_detach(BPFProgram *p) { - return 0; - } - -+void bpf_program_skeletonize(BPFProgram *p) { -+ assert(p); -+ -+ /* Called shortly after serialization. From this point on, we are frozen for serialization and entry -+ * into BPF limbo, so we should proactively free our instructions and attached path. However, we -+ * shouldn't detach the program or close the kernel FD -- we need those on the other side. */ -+ free(p->instructions); -+ free(p->attached_path); -+} -+ - int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) { - union bpf_attr attr = { - .map_type = type, -diff --git a/src/shared/bpf-program.h b/src/shared/bpf-program.h -index a21589eb1f..6ea5d9a57c 100644 ---- a/src/shared/bpf-program.h -+++ b/src/shared/bpf-program.h -@@ -28,6 +28,7 @@ struct BPFProgram { - int bpf_program_new(uint32_t prog_type, BPFProgram **ret); - BPFProgram *bpf_program_unref(BPFProgram *p); - BPFProgram *bpf_program_ref(BPFProgram *p); -+void bpf_program_skeletonize(BPFProgram *p); - - int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count); - int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size); --- -2.24.1 - diff --git a/SOURCES/0001-test-acl-util-output-more-debug-info.patch b/SOURCES/0001-test-acl-util-output-more-debug-info.patch deleted file mode 100644 index 6db830f..0000000 --- a/SOURCES/0001-test-acl-util-output-more-debug-info.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 8cad57ed62a642515670ba79dddb30193456e803 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Fri, 7 Aug 2020 18:54:37 +0200 -Subject: [PATCH] test-acl-util: output more debug info - -For some reason this failed in koji build on s390x: ---- command --- -16:12:46 PATH='/builddir/build/BUILD/systemd-stable-246.1/s390x-redhat-linux-gnu:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/sbin' SYSTEMD_LANGUAGE_FALLBACK_MAP='/builddir/build/BUILD/systemd-stable-246.1/src/locale/language-fallback-map' SYSTEMD_KBD_MODEL_MAP='/builddir/build/BUILD/systemd-stable-246.1/src/locale/kbd-model-map' /builddir/build/BUILD/systemd-stable-246.1/s390x-redhat-linux-gnu/test-acl-util ---- stdout --- --rw-r-----. 1 mockbuild mock 0 Aug 7 16:12 /tmp/test-empty.7RzmEc -other::--- ---- stderr --- -Assertion 'r >= 0' failed at src/test/test-acl-util.c:42, function test_add_acls_for_user(). Aborting. ---- - src/test/test-acl-util.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/test/test-acl-util.c b/src/test/test-acl-util.c -index df879747f5..9f0e594e67 100644 ---- a/src/test/test-acl-util.c -+++ b/src/test/test-acl-util.c -@@ -7,6 +7,7 @@ - - #include "acl-util.h" - #include "fd-util.h" -+#include "format-util.h" - #include "string-util.h" - #include "tmpfile-util.h" - #include "user-util.h" -@@ -18,6 +19,8 @@ static void test_add_acls_for_user(void) { - uid_t uid; - int r; - -+ log_info("/* %s */", __func__); -+ - fd = mkostemp_safe(fn); - assert_se(fd >= 0); - -@@ -39,6 +42,7 @@ static void test_add_acls_for_user(void) { - uid = getuid(); - - r = add_acls_for_user(fd, uid); -+ log_info_errno(r, "add_acls_for_user(%d, "UID_FMT"): %m", fd, uid); - assert_se(r >= 0); - - cmd = strjoina("ls -l ", fn); diff --git a/SOURCES/0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch b/SOURCES/0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch deleted file mode 100644 index d2a5150..0000000 --- a/SOURCES/0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch +++ /dev/null @@ -1,124 +0,0 @@ -From b554f941a8f275124508794b0b83f0554c7b84dc Mon Sep 17 00:00:00 2001 -From: Anita Zhang -Date: Thu, 22 Oct 2020 22:44:22 -0700 -Subject: [PATCH 2/3] core: clean up inactive/failed {service|scope}'s cgroups - when the last process exits - -If processes remain in the unit's cgroup after the final SIGKILL is -sent and the unit has exceeded stop timeout, don't release the unit's -cgroup information. Pid1 will have failed to `rmdir` the cgroup path due -to processes remaining in the cgroup and releasing would leave the cgroup -path on the file system with no tracking for pid1 to clean it up. - -Instead, keep the information around until the last process exits and pid1 -sends the cgroup empty notification. The service/scope can then prune -the cgroup if the unit is inactive/failed. ---- - src/core/cgroup.c | 26 +++++++++++++++++++++++++- - src/core/cgroup.h | 6 +++++- - src/core/scope.c | 5 +++++ - src/core/service.c | 7 +++++++ - 4 files changed, 42 insertions(+), 2 deletions(-) - -diff --git a/src/core/cgroup.c b/src/core/cgroup.c -index 031b28a684..bce5f44e78 100644 ---- a/src/core/cgroup.c -+++ b/src/core/cgroup.c -@@ -2414,6 +2414,29 @@ void unit_release_cgroup(Unit *u) { - } - } - -+bool unit_maybe_release_cgroup(Unit *u) { -+ int r; -+ -+ assert(u); -+ -+ if (!u->cgroup_path) -+ return true; -+ -+ /* Don't release the cgroup if there are still processes under it. If we get notified later when all the -+ * processes exit (e.g. the processes were in D-state and exited after the unit was marked as failed) -+ * we need the cgroup paths to continue to be tracked by the manager so they can be looked up and cleaned -+ * up later. */ -+ r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path); -+ if (r < 0) -+ log_unit_debug_errno(u, r, "Error checking if the cgroup is recursively empty, ignoring: %m"); -+ else if (r == 1) { -+ unit_release_cgroup(u); -+ return true; -+ } -+ -+ return false; -+} -+ - void unit_prune_cgroup(Unit *u) { - int r; - bool is_root_slice; -@@ -2441,7 +2464,8 @@ void unit_prune_cgroup(Unit *u) { - if (is_root_slice) - return; - -- unit_release_cgroup(u); -+ if (!unit_maybe_release_cgroup(u)) /* Returns true if the cgroup was released */ -+ return; - - u->cgroup_realized = false; - u->cgroup_realized_mask = 0; -diff --git a/src/core/cgroup.h b/src/core/cgroup.h -index 52d028e740..be6856c20c 100644 ---- a/src/core/cgroup.h -+++ b/src/core/cgroup.h -@@ -220,11 +220,15 @@ int unit_set_cgroup_path(Unit *u, const char *path); - int unit_pick_cgroup_path(Unit *u); - - int unit_realize_cgroup(Unit *u); --void unit_release_cgroup(Unit *u); - void unit_prune_cgroup(Unit *u); - int unit_watch_cgroup(Unit *u); - int unit_watch_cgroup_memory(Unit *u); - -+void unit_release_cgroup(Unit *u); -+/* Releases the cgroup only if it is recursively empty. -+ * Returns true if the cgroup was released, false otherwise. */ -+bool unit_maybe_release_cgroup(Unit *u); -+ - void unit_add_to_cgroup_empty_queue(Unit *u); - int unit_check_oom(Unit *u); - -diff --git a/src/core/scope.c b/src/core/scope.c -index 42c51b0865..ffee783a4c 100644 ---- a/src/core/scope.c -+++ b/src/core/scope.c -@@ -487,6 +487,11 @@ static void scope_notify_cgroup_empty_event(Unit *u) { - - if (IN_SET(s->state, SCOPE_RUNNING, SCOPE_ABANDONED, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) - scope_enter_dead(s, SCOPE_SUCCESS); -+ -+ /* If the cgroup empty notification comes when the unit is not active, we must have failed to clean -+ * up the cgroup earlier and should do it now. */ -+ if (IN_SET(s->state, SCOPE_DEAD, SCOPE_FAILED)) -+ unit_prune_cgroup(u); - } - - static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { -diff --git a/src/core/service.c b/src/core/service.c -index 00e61945ba..db8f596ca6 100644 ---- a/src/core/service.c -+++ b/src/core/service.c -@@ -3334,6 +3334,13 @@ static void service_notify_cgroup_empty_event(Unit *u) { - - break; - -+ /* If the cgroup empty notification comes when the unit is not active, we must have failed to clean -+ * up the cgroup earlier and should do it now. */ -+ case SERVICE_DEAD: -+ case SERVICE_FAILED: -+ unit_prune_cgroup(u); -+ break; -+ - default: - ; - } --- -2.24.1 - diff --git a/SOURCES/0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch b/SOURCES/0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch deleted file mode 100644 index c285891..0000000 --- a/SOURCES/0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch +++ /dev/null @@ -1,53 +0,0 @@ -From a2deeaeaa90d493ef8a2b20656745cd0531a1b30 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Fri, 31 Jul 2020 10:36:57 +0200 -Subject: [PATCH 2/2] test-path: do not fail the test if we fail to start some - service - -The test was failing because it couldn't start the service: - -path-modified.service: state = failed; result = exit-code -path-modified.path: state = waiting; result = success -path-modified.service: state = failed; result = exit-code -path-modified.path: state = waiting; result = success -path-modified.service: state = failed; result = exit-code -path-modified.path: state = waiting; result = success -path-modified.service: state = failed; result = exit-code -path-modified.path: state = waiting; result = success -path-modified.service: state = failed; result = exit-code -path-modified.path: state = waiting; result = success -path-modified.service: state = failed; result = exit-code -Failed to connect to system bus: No such file or directory --.slice: Failed to enable/disable controllers on cgroup /system.slice/kojid.service, ignoring: Permission denied -path-modified.service: Failed to create cgroup /system.slice/kojid.service/path-modified.service: Permission denied -path-modified.service: Failed to attach to cgroup /system.slice/kojid.service/path-modified.service: No such file or directory -path-modified.service: Failed at step CGROUP spawning /bin/true: No such file or directory -path-modified.service: Main process exited, code=exited, status=219/CGROUP -path-modified.service: Failed with result 'exit-code'. -Test timeout when testing path-modified.path - -Let's just ignore the failure here. Services can occasionally fail to start, -there's not much we can do in that case. ---- - src/test/test-path.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/src/test/test-path.c b/src/test/test-path.c -index 63b709c8da..6c0db53f10 100644 ---- a/src/test/test-path.c -+++ b/src/test/test-path.c -@@ -98,6 +98,14 @@ static void check_states(Manager *m, Path *path, Service *service, PathState pat - service_state_to_string(service->state), - service_result_to_string(service->result)); - -+ if (service->state == SERVICE_FAILED) { -+ log_warning("Failed to start service %s, ignoring: %s/%s", -+ UNIT(service)->id, -+ service_state_to_string(service->state), -+ service_result_to_string(service->result)); -+ break; -+ } -+ - if (now(CLOCK_MONOTONIC) >= end) { - log_error("Test timeout when testing %s", UNIT(path)->id); - exit(EXIT_FAILURE); diff --git a/SOURCES/0003-timer-add-new-feature-FixedRandomDelay.patch b/SOURCES/0003-timer-add-new-feature-FixedRandomDelay.patch deleted file mode 100644 index a1559c8..0000000 --- a/SOURCES/0003-timer-add-new-feature-FixedRandomDelay.patch +++ /dev/null @@ -1,234 +0,0 @@ -From de8f6fb530db706d14e9ece52b2acfd77c823133 Mon Sep 17 00:00:00 2001 -From: Kristijan Gjoshev -Date: Sat, 1 Feb 2020 18:27:08 +0100 -Subject: [PATCH 3/3] timer: add new feature FixedRandomDelay= - -FixedRandomDelay=yes will use -`siphash24(sd_id128_get_machine() || MANAGER_IS_SYSTEM(m) || getuid() || u->id)`, -where || is concatenation, instead of a random number to choose a value between -0 and RandomizedDelaySec= as the timer delay. -This essentially sets up a fixed, but seemingly random, offset for each timer -iteration rather than having a random offset recalculated each time it fires. - -Closes #10355 - -Co-author: Anita Zhang ---- - docs/TRANSIENT-SETTINGS.md | 1 + - man/org.freedesktop.systemd1.xml | 6 ++++ - man/systemd.timer.xml | 12 +++++++ - src/core/dbus-timer.c | 4 +++ - src/core/timer.c | 34 ++++++++++++++++++- - src/core/timer.h | 1 + - src/shared/bus-unit-util.c | 3 +- - test/fuzz/fuzz-unit-file/directives.service | 1 + - .../systemd-tmpfiles-clean.timer | 1 + - 9 files changed, 61 insertions(+), 2 deletions(-) - -diff --git a/docs/TRANSIENT-SETTINGS.md b/docs/TRANSIENT-SETTINGS.md -index 19944d08b8..f4639b2e87 100644 ---- a/docs/TRANSIENT-SETTINGS.md -+++ b/docs/TRANSIENT-SETTINGS.md -@@ -368,6 +368,7 @@ Most timer unit settings are available to transient units. - ✓ RemainAfterElapse= - ✓ AccuracySec= - ✓ RandomizedDelaySec= -+✓ FixedRandomDelay= - Unit= - ``` - -diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml -index 6b16ae16da..ab4cbaa2fb 100644 ---- a/man/org.freedesktop.systemd1.xml -+++ b/man/org.freedesktop.systemd1.xml -@@ -6866,6 +6866,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly t RandomizedDelayUSec = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") -+ readonly b FixedRandomDelay = ...; -+ @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b Persistent = ...; - @org.freedesktop.DBus.Property.EmitsChangedSignal("const") - readonly b WakeSystem = ...; -@@ -6891,6 +6893,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { - - - -+ -+ - - - -@@ -6931,6 +6935,8 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { - - - -+ -+ - - - -diff --git a/man/systemd.timer.xml b/man/systemd.timer.xml -index 5822402712..6f731e2311 100644 ---- a/man/systemd.timer.xml -+++ b/man/systemd.timer.xml -@@ -268,6 +268,18 @@ - AccuracySec=1us. - - -+ -+ FixedRandomDelay= -+ -+ Takes a boolean argument. If true, some amount of time between 0 and -+ RandomizedDelaySec= is chosen and added as the delay for each timer iteration. As this -+ delay will not be recalculated on each run, this effectively creates a fixed offset for each iteration. -+ The distribution between 0 and RandomizedDelaySec= is deterministic and based on -+ a combination of the machine ID, whether the timer is run by the user/system manager, the service manager's -+ user ID, and the timer's unit name. Has no effect if -+ RandomizedDelaySec= is set to 0. Defaults to . -+ -+ - - OnClockChange= - OnTimezoneChange= -diff --git a/src/core/dbus-timer.c b/src/core/dbus-timer.c -index da35fa8678..ee54ba8772 100644 ---- a/src/core/dbus-timer.c -+++ b/src/core/dbus-timer.c -@@ -131,6 +131,7 @@ const sd_bus_vtable bus_timer_vtable[] = { - SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Timer, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_PROPERTY("AccuracyUSec", "t", bus_property_get_usec, offsetof(Timer, accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RandomizedDelayUSec", "t", bus_property_get_usec, offsetof(Timer, random_usec), SD_BUS_VTABLE_PROPERTY_CONST), -+ SD_BUS_PROPERTY("FixedRandomDelay", "b", bus_property_get_bool, offsetof(Timer, fixed_random_delay), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("Persistent", "b", bus_property_get_bool, offsetof(Timer, persistent), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("WakeSystem", "b", bus_property_get_bool, offsetof(Timer, wake_system), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("RemainAfterElapse", "b", bus_property_get_bool, offsetof(Timer, remain_after_elapse), SD_BUS_VTABLE_PROPERTY_CONST), -@@ -232,6 +233,9 @@ static int bus_timer_set_transient_property( - if (streq(name, "RandomizedDelayUSec")) - return bus_set_transient_usec(u, name, &t->random_usec, message, flags, error); - -+ if (streq(name, "FixedRandomDelay")) -+ return bus_set_transient_bool(u, name, &t->fixed_random_delay, message, flags, error); -+ - if (streq(name, "WakeSystem")) - return bus_set_transient_bool(u, name, &t->wake_system, message, flags, error); - -diff --git a/src/core/timer.c b/src/core/timer.c -index 03a9c14f76..b2c5e26f63 100644 ---- a/src/core/timer.c -+++ b/src/core/timer.c -@@ -169,6 +169,36 @@ static int timer_setup_persistent(Timer *t) { - return 0; - } - -+static uint64_t timer_get_fixed_delay_hash(Timer *t) { -+ static const uint8_t hash_key[] = { -+ 0x51, 0x0a, 0xdb, 0x76, 0x29, 0x51, 0x42, 0xc2, -+ 0x80, 0x35, 0xea, 0xe6, 0x8e, 0x3a, 0x37, 0xbd -+ }; -+ -+ struct siphash state; -+ sd_id128_t machine_id; -+ uid_t uid; -+ int r; -+ -+ assert(t); -+ -+ uid = getuid(); -+ r = sd_id128_get_machine(&machine_id); -+ if (r < 0) { -+ log_unit_debug_errno(UNIT(t), r, -+ "Failed to get machine ID for the fixed delay calculation, proceeding with 0: %m"); -+ machine_id = SD_ID128_NULL; -+ } -+ -+ siphash24_init(&state, hash_key); -+ siphash24_compress(&machine_id, sizeof(sd_id128_t), &state); -+ siphash24_compress_boolean(MANAGER_IS_SYSTEM(UNIT(t)->manager), &state); -+ siphash24_compress(&uid, sizeof(uid_t), &state); -+ siphash24_compress_string(UNIT(t)->id, &state); -+ -+ return siphash24_finalize(&state); -+} -+ - static int timer_load(Unit *u) { - Timer *t = TIMER(u); - int r; -@@ -215,6 +245,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { - "%sWakeSystem: %s\n" - "%sAccuracy: %s\n" - "%sRemainAfterElapse: %s\n" -+ "%sFixedRandomDelay: %s\n" - "%sOnClockChange: %s\n" - "%sOnTimeZoneChange: %s\n", - prefix, timer_state_to_string(t->state), -@@ -224,6 +255,7 @@ static void timer_dump(Unit *u, FILE *f, const char *prefix) { - prefix, yes_no(t->wake_system), - prefix, format_timespan(buf, sizeof(buf), t->accuracy_usec, 1), - prefix, yes_no(t->remain_after_elapse), -+ prefix, yes_no(t->fixed_random_delay), - prefix, yes_no(t->on_clock_change), - prefix, yes_no(t->on_timezone_change)); - -@@ -332,7 +364,7 @@ static void add_random(Timer *t, usec_t *v) { - if (*v == USEC_INFINITY) - return; - -- add = random_u64() % t->random_usec; -+ add = (t->fixed_random_delay ? timer_get_fixed_delay_hash(t) : random_u64()) % t->random_usec; - - if (*v + add < *v) /* overflow */ - *v = (usec_t) -2; /* Highest possible value, that is not USEC_INFINITY */ -diff --git a/src/core/timer.h b/src/core/timer.h -index ab66a201ad..ce4046a210 100644 ---- a/src/core/timer.h -+++ b/src/core/timer.h -@@ -59,6 +59,7 @@ struct Timer { - bool remain_after_elapse; - bool on_clock_change; - bool on_timezone_change; -+ bool fixed_random_delay; - - char *stamp_path; - }; -diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c -index f2652ed9a5..68de4a2ed1 100644 ---- a/src/shared/bus-unit-util.c -+++ b/src/shared/bus-unit-util.c -@@ -1779,7 +1779,8 @@ static int bus_append_timer_property(sd_bus_message *m, const char *field, const - "RemainAfterElapse", - "Persistent", - "OnTimezoneChange", -- "OnClockChange")) -+ "OnClockChange", -+ "FixedRandomDelay")) - return bus_append_parse_boolean(m, field, eq); - - if (STR_IN_SET(field, "AccuracySec", -diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service -index dbff9ab2cc..95304ea0c6 100644 ---- a/test/fuzz/fuzz-unit-file/directives.service -+++ b/test/fuzz/fuzz-unit-file/directives.service -@@ -175,6 +175,7 @@ PipeSize= - Priority= - PropagatesReloadTo= - RandomizedDelaySec= -+FixedRandomDelay= - RebootArgument= - ReceiveBuffer= - RefuseManualStart= -diff --git a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer -index 7db361cd69..64b8808adc 100644 ---- a/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer -+++ b/test/fuzz/fuzz-unit-file/systemd-tmpfiles-clean.timer -@@ -32,6 +32,7 @@ OnCalendar=Fri 2012-11-23 11:12:13 - Persistent=true - AccuracySec=24h - RandomizedDelaySec=234234234 -+FixedRandomDelay=true - - Persistent=no - Unit=foo.service --- -2.24.1 - diff --git a/SOURCES/16803_fix_asserts_conditions.patch b/SOURCES/16803_fix_asserts_conditions.patch deleted file mode 100644 index 817ec45..0000000 --- a/SOURCES/16803_fix_asserts_conditions.patch +++ /dev/null @@ -1,553 +0,0 @@ -From 625a164069aff9efb61dcc5916c572f53c2a7ab0 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 20 Aug 2020 13:43:00 +0200 -Subject: [PATCH 1/3] analyze: rework condition testing - -Let's drop the private table and just use the generic concepts we have -in place already that make the same information available. - -Fixes: #16781 ---- - src/analyze/analyze-condition.c | 105 +++++++++----------------------- - 1 file changed, 28 insertions(+), 77 deletions(-) - -diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c -index 52ad382637f..13f75e813a2 100644 ---- a/src/analyze/analyze-condition.c -+++ b/src/analyze/analyze-condition.c -@@ -8,83 +8,27 @@ - #include "load-fragment.h" - #include "service.h" - --typedef struct condition_definition { -- const char *name; -- ConfigParserCallback parser; -- ConditionType type; --} condition_definition; -- --static const condition_definition condition_definitions[] = { -- { "ConditionPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, -- { "ConditionPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, -- { "ConditionPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, -- { "ConditionPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, -- { "ConditionPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, -- { "ConditionPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, -- { "ConditionPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, -- { "ConditionDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, -- { "ConditionFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, -- { "ConditionFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, -- { "ConditionNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, -- { "ConditionFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, -- { "ConditionKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, -- { "ConditionKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, -- { "ConditionArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, -- { "ConditionVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, -- { "ConditionSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, -- { "ConditionCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, -- { "ConditionHost", config_parse_unit_condition_string, CONDITION_HOST }, -- { "ConditionACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, -- { "ConditionUser", config_parse_unit_condition_string, CONDITION_USER }, -- { "ConditionGroup", config_parse_unit_condition_string, CONDITION_GROUP }, -- { "ConditionControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, -- -- { "AssertPathExists", config_parse_unit_condition_path, CONDITION_PATH_EXISTS }, -- { "AssertPathExistsGlob", config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB }, -- { "AssertPathIsDirectory", config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY }, -- { "AssertPathIsSymbolicLink", config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK }, -- { "AssertPathIsMountPoint", config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT }, -- { "AssertPathIsReadWrite", config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE }, -- { "AssertPathIsEncrypted", config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED }, -- { "AssertDirectoryNotEmpty", config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY }, -- { "AssertFileNotEmpty", config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY }, -- { "AssertFileIsExecutable", config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE }, -- { "AssertNeedsUpdate", config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE }, -- { "AssertFirstBoot", config_parse_unit_condition_string, CONDITION_FIRST_BOOT }, -- { "AssertKernelCommandLine", config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE }, -- { "AssertKernelVersion", config_parse_unit_condition_string, CONDITION_KERNEL_VERSION }, -- { "AssertArchitecture", config_parse_unit_condition_string, CONDITION_ARCHITECTURE }, -- { "AssertVirtualization", config_parse_unit_condition_string, CONDITION_VIRTUALIZATION }, -- { "AssertSecurity", config_parse_unit_condition_string, CONDITION_SECURITY }, -- { "AssertCapability", config_parse_unit_condition_string, CONDITION_CAPABILITY }, -- { "AssertHost", config_parse_unit_condition_string, CONDITION_HOST }, -- { "AssertACPower", config_parse_unit_condition_string, CONDITION_AC_POWER }, -- { "AssertUser", config_parse_unit_condition_string, CONDITION_USER }, -- { "AssertGroup", config_parse_unit_condition_string, CONDITION_GROUP }, -- { "AssertControlGroupController", config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER }, -- -- /* deprecated, but we should still parse them */ -- { "ConditionNull", config_parse_unit_condition_null, 0 }, -- { "AssertNull", config_parse_unit_condition_null, 0 }, --}; -- - static int parse_condition(Unit *u, const char *line) { -- const char *p; -- Condition **target; -- -- if ((p = startswith(line, "Condition"))) -- target = &u->conditions; -- else if ((p = startswith(line, "Assert"))) -- target = &u->asserts; -- else -- return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); -- -- for (size_t i = 0; i < ELEMENTSOF(condition_definitions); i++) { -- const condition_definition *c = &condition_definitions[i]; -- -- p = startswith(line, c->name); -- if (!p) -- continue; -+ assert(u); -+ assert(line); -+ -+ for (ConditionType t = 0; t < _CONDITION_TYPE_MAX; t++) { -+ ConfigParserCallback callback; -+ Condition **target; -+ const char *p, *name; -+ -+ name = condition_type_to_string(t); -+ p = startswith(line, name); -+ if (p) -+ target = &u->conditions; -+ else { -+ name = assert_type_to_string(t); -+ p = startswith(line, name); -+ if (!p) -+ continue; -+ -+ target = &u->asserts; -+ } - - p += strspn(p, WHITESPACE); - -@@ -94,7 +38,14 @@ static int parse_condition(Unit *u, const char *line) { - - p += strspn(p, WHITESPACE); - -- return c->parser(NULL, "(stdin)", 0, NULL, 0, c->name, c->type, p, target, u); -+ if (t == CONDITION_NULL) /* deprecated, but we should still parse this for now */ -+ callback = config_parse_unit_condition_null; -+ else if (condition_takes_path(t)) -+ callback = config_parse_unit_condition_path; -+ else -+ callback = config_parse_unit_condition_string; -+ -+ return callback(NULL, "(cmdline)", 0, NULL, 0, name, t, p, target, u); - } - - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot parse \"%s\".", line); - -From 4f55a5b0bf1e68e4595120d8ac4b518654355fc3 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 20 Aug 2020 13:44:12 +0200 -Subject: [PATCH 2/3] core: add missing conditions/asserts to unit file parsing - ---- - src/core/load-fragment-gperf.gperf.m4 | 24 ++++++++++++++++-------- - 1 file changed, 16 insertions(+), 8 deletions(-) - -diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 -index b9e7769e4e3..1e6bd6483c2 100644 ---- a/src/core/load-fragment-gperf.gperf.m4 -+++ b/src/core/load-fragment-gperf.gperf.m4 -@@ -272,22 +272,26 @@ Unit.ConditionPathIsDirectory, config_parse_unit_condition_path, CONDITION_P - Unit.ConditionPathIsSymbolicLink,config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, conditions) - Unit.ConditionPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, conditions) - Unit.ConditionPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, conditions) -+Unit.ConditionPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, conditions) - Unit.ConditionDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, conditions) - Unit.ConditionFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, conditions) - Unit.ConditionFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, conditions) - Unit.ConditionNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, conditions) - Unit.ConditionFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, conditions) --Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) --Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) - Unit.ConditionArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, conditions) - Unit.ConditionVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, conditions) -+Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) -+Unit.ConditionKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, conditions) -+Unit.ConditionKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, conditions) - Unit.ConditionSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, conditions) - Unit.ConditionCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, conditions) --Unit.ConditionHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, conditions) - Unit.ConditionACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, conditions) -+Unit.ConditionMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, conditions) -+Unit.ConditionCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, conditions) -+Unit.ConditionEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, conditions) - Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions) - Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions) --Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) -+Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) - Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions) - Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts) - Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts) -@@ -295,22 +299,26 @@ Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_P - Unit.AssertPathIsSymbolicLink, config_parse_unit_condition_path, CONDITION_PATH_IS_SYMBOLIC_LINK,offsetof(Unit, asserts) - Unit.AssertPathIsMountPoint, config_parse_unit_condition_path, CONDITION_PATH_IS_MOUNT_POINT, offsetof(Unit, asserts) - Unit.AssertPathIsReadWrite, config_parse_unit_condition_path, CONDITION_PATH_IS_READ_WRITE, offsetof(Unit, asserts) -+Unit.AssertPathIsEncrypted, config_parse_unit_condition_path, CONDITION_PATH_IS_ENCRYPTED, offsetof(Unit, asserts) - Unit.AssertDirectoryNotEmpty, config_parse_unit_condition_path, CONDITION_DIRECTORY_NOT_EMPTY, offsetof(Unit, asserts) - Unit.AssertFileNotEmpty, config_parse_unit_condition_path, CONDITION_FILE_NOT_EMPTY, offsetof(Unit, asserts) - Unit.AssertFileIsExecutable, config_parse_unit_condition_path, CONDITION_FILE_IS_EXECUTABLE, offsetof(Unit, asserts) - Unit.AssertNeedsUpdate, config_parse_unit_condition_path, CONDITION_NEEDS_UPDATE, offsetof(Unit, asserts) - Unit.AssertFirstBoot, config_parse_unit_condition_string, CONDITION_FIRST_BOOT, offsetof(Unit, asserts) --Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) --Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) - Unit.AssertArchitecture, config_parse_unit_condition_string, CONDITION_ARCHITECTURE, offsetof(Unit, asserts) - Unit.AssertVirtualization, config_parse_unit_condition_string, CONDITION_VIRTUALIZATION, offsetof(Unit, asserts) -+Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) -+Unit.AssertKernelCommandLine, config_parse_unit_condition_string, CONDITION_KERNEL_COMMAND_LINE, offsetof(Unit, asserts) -+Unit.AssertKernelVersion, config_parse_unit_condition_string, CONDITION_KERNEL_VERSION, offsetof(Unit, asserts) - Unit.AssertSecurity, config_parse_unit_condition_string, CONDITION_SECURITY, offsetof(Unit, asserts) - Unit.AssertCapability, config_parse_unit_condition_string, CONDITION_CAPABILITY, offsetof(Unit, asserts) --Unit.AssertHost, config_parse_unit_condition_string, CONDITION_HOST, offsetof(Unit, asserts) - Unit.AssertACPower, config_parse_unit_condition_string, CONDITION_AC_POWER, offsetof(Unit, asserts) -+Unit.AssertMemory, config_parse_unit_condition_string, CONDITION_MEMORY, offsetof(Unit, asserts) -+Unit.AssertCPUs, config_parse_unit_condition_string, CONDITION_CPUS, offsetof(Unit, asserts) -+Unit.AssertEnvironment, config_parse_unit_condition_string, CONDITION_ENVIRONMENT, offsetof(Unit, asserts) - Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts) - Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts) --Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) -+Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) - Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) - Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode) - m4_dnl - -From 476cfe626dac41bb9879116c701333caa2ccec24 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 20 Aug 2020 14:01:25 +0200 -Subject: [PATCH 3/3] core: remove support for ConditionNull= - -The concept is flawed, and mostly useless. Let's finally remove it. - -It has been deprecated since 90a2ec10f2d43a8530aae856013518eb567c4039 (6 -years ago) and we started to warn since -55dadc5c57ef1379dbc984938d124508a454be55 (1.5 years ago). - -Let's get rid of it altogether. ---- - man/systemd.unit.xml | 3 - - src/analyze/analyze-condition.c | 4 +- - src/core/dbus-unit.c | 22 +++----- - src/core/load-fragment-gperf.gperf.m4 | 2 - - src/core/load-fragment.c | 55 ------------------- - src/core/load-fragment.h | 1 - - src/shared/condition.c | 21 +------ - src/shared/condition.h | 2 - - src/test/test-condition.c | 15 ----- - .../fuzz-unit-file/systemd-machined.service | 3 - - 10 files changed, 11 insertions(+), 117 deletions(-) - -diff --git a/man/systemd.unit.xml b/man/systemd.unit.xml -index 7ef6080237e..50f35aaa3cc 100644 ---- a/man/systemd.unit.xml -+++ b/man/systemd.unit.xml -@@ -1092,9 +1092,6 @@ - Except for ConditionPathIsSymbolicLink=, all path checks follow symlinks. - - -- -- - - ConditionArchitecture= - -diff --git a/src/analyze/analyze-condition.c b/src/analyze/analyze-condition.c -index 13f75e813a2..e1365e18056 100644 ---- a/src/analyze/analyze-condition.c -+++ b/src/analyze/analyze-condition.c -@@ -38,9 +38,7 @@ static int parse_condition(Unit *u, const char *line) { - - p += strspn(p, WHITESPACE); - -- if (t == CONDITION_NULL) /* deprecated, but we should still parse this for now */ -- callback = config_parse_unit_condition_null; -- else if (condition_takes_path(t)) -+ if (condition_takes_path(t)) - callback = config_parse_unit_condition_path; - else - callback = config_parse_unit_condition_string; -diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c -index 9e9d3b101e5..e799771c220 100644 ---- a/src/core/dbus-unit.c -+++ b/src/core/dbus-unit.c -@@ -1974,14 +1974,11 @@ static int bus_set_transient_conditions( - if (t < 0) - return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid condition type: %s", type_name); - -- if (t != CONDITION_NULL) { -- if (isempty(param)) -- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name); -+ if (isempty(param)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Condition parameter in %s is empty", type_name); - -- if (condition_takes_path(t) && !path_is_absolute(param)) -- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param); -- } else -- param = NULL; -+ if (condition_takes_path(t) && !path_is_absolute(param)) -+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path in condition %s is not absolute: %s", type_name, param); - - if (!UNIT_WRITE_FLAGS_NOOP(flags)) { - Condition *c; -@@ -1992,14 +1989,9 @@ static int bus_set_transient_conditions( - - LIST_PREPEND(conditions, *list, c); - -- if (t != CONDITION_NULL) -- unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, -- "%s=%s%s%s", type_name, -- trigger ? "|" : "", negate ? "!" : "", param); -- else -- unit_write_settingf(u, flags, name, -- "%s=%s%s", type_name, -- trigger ? "|" : "", yes_no(!negate)); -+ unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, -+ "%s=%s%s%s", type_name, -+ trigger ? "|" : "", negate ? "!" : "", param); - } - - empty = false; -diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 -index 1e6bd6483c2..a191de62af3 100644 ---- a/src/core/load-fragment-gperf.gperf.m4 -+++ b/src/core/load-fragment-gperf.gperf.m4 -@@ -292,7 +292,6 @@ Unit.ConditionEnvironment, config_parse_unit_condition_string, CONDITION_E - Unit.ConditionUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, conditions) - Unit.ConditionGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, conditions) - Unit.ConditionControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, conditions) --Unit.ConditionNull, config_parse_unit_condition_null, 0, offsetof(Unit, conditions) - Unit.AssertPathExists, config_parse_unit_condition_path, CONDITION_PATH_EXISTS, offsetof(Unit, asserts) - Unit.AssertPathExistsGlob, config_parse_unit_condition_path, CONDITION_PATH_EXISTS_GLOB, offsetof(Unit, asserts) - Unit.AssertPathIsDirectory, config_parse_unit_condition_path, CONDITION_PATH_IS_DIRECTORY, offsetof(Unit, asserts) -@@ -319,7 +318,6 @@ Unit.AssertEnvironment, config_parse_unit_condition_string, CONDITION_E - Unit.AssertUser, config_parse_unit_condition_string, CONDITION_USER, offsetof(Unit, asserts) - Unit.AssertGroup, config_parse_unit_condition_string, CONDITION_GROUP, offsetof(Unit, asserts) - Unit.AssertControlGroupController, config_parse_unit_condition_string, CONDITION_CONTROL_GROUP_CONTROLLER, offsetof(Unit, asserts) --Unit.AssertNull, config_parse_unit_condition_null, 0, offsetof(Unit, asserts) - Unit.CollectMode, config_parse_collect_mode, 0, offsetof(Unit, collect_mode) - m4_dnl - Service.PIDFile, config_parse_pid_file, 0, offsetof(Service, pid_file) -diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c -index 266382c84c7..cfd04f3b49f 100644 ---- a/src/core/load-fragment.c -+++ b/src/core/load-fragment.c -@@ -2999,60 +2999,6 @@ int config_parse_unit_condition_string( - return 0; - } - --int config_parse_unit_condition_null( -- const char *unit, -- const char *filename, -- unsigned line, -- const char *section, -- unsigned section_line, -- const char *lvalue, -- int ltype, -- const char *rvalue, -- void *data, -- void *userdata) { -- -- Condition **list = data, *c; -- bool trigger, negate; -- int b; -- -- assert(filename); -- assert(lvalue); -- assert(rvalue); -- assert(data); -- -- log_syntax(unit, LOG_WARNING, filename, line, 0, "%s= is deprecated, please do not use.", lvalue); -- -- if (isempty(rvalue)) { -- /* Empty assignment resets the list */ -- *list = condition_free_list(*list); -- return 0; -- } -- -- trigger = rvalue[0] == '|'; -- if (trigger) -- rvalue++; -- -- negate = rvalue[0] == '!'; -- if (negate) -- rvalue++; -- -- b = parse_boolean(rvalue); -- if (b < 0) { -- log_syntax(unit, LOG_ERR, filename, line, b, "Failed to parse boolean value in condition, ignoring: %s", rvalue); -- return 0; -- } -- -- if (!b) -- negate = !negate; -- -- c = condition_new(CONDITION_NULL, NULL, trigger, negate); -- if (!c) -- return log_oom(); -- -- LIST_PREPEND(conditions, *list, c); -- return 0; --} -- - int config_parse_unit_requires_mounts_for( - const char *unit, - const char *filename, -@@ -5266,7 +5212,6 @@ void unit_dump_config_items(FILE *f) { - { config_parse_ip_tos, "TOS" }, - { config_parse_unit_condition_path, "CONDITION" }, - { config_parse_unit_condition_string, "CONDITION" }, -- { config_parse_unit_condition_null, "CONDITION" }, - { config_parse_unit_slice, "SLICE" }, - { config_parse_documentation, "URL" }, - { config_parse_service_timeout, "SECONDS" }, -diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h -index 2672db5ace2..cee5717d0fb 100644 ---- a/src/core/load-fragment.h -+++ b/src/core/load-fragment.h -@@ -58,7 +58,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_unit_env_file); - CONFIG_PARSER_PROTOTYPE(config_parse_ip_tos); - CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_path); - CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_string); --CONFIG_PARSER_PROTOTYPE(config_parse_unit_condition_null); - CONFIG_PARSER_PROTOTYPE(config_parse_kill_mode); - CONFIG_PARSER_PROTOTYPE(config_parse_notify_access); - CONFIG_PARSER_PROTOTYPE(config_parse_emergency_action); -diff --git a/src/shared/condition.c b/src/shared/condition.c -index bf3b5fa1622..1f6105622a5 100644 ---- a/src/shared/condition.c -+++ b/src/shared/condition.c -@@ -52,7 +52,7 @@ Condition* condition_new(ConditionType type, const char *parameter, bool trigger - - assert(type >= 0); - assert(type < _CONDITION_TYPE_MAX); -- assert((!parameter) == (type == CONDITION_NULL)); -+ assert(parameter); - - c = new(Condition, 1); - if (!c) -@@ -776,15 +776,6 @@ static int condition_test_file_is_executable(Condition *c, char **env) { - (st.st_mode & 0111)); - } - --static int condition_test_null(Condition *c, char **env) { -- assert(c); -- assert(c->type == CONDITION_NULL); -- -- /* Note that during parsing we already evaluate the string and -- * store it in c->negate */ -- return true; --} -- - int condition_test(Condition *c, char **env) { - - static int (*const condition_tests[_CONDITION_TYPE_MAX])(Condition *c, char **env) = { -@@ -811,7 +802,6 @@ int condition_test(Condition *c, char **env) { - [CONDITION_USER] = condition_test_user, - [CONDITION_GROUP] = condition_test_group, - [CONDITION_CONTROL_GROUP_CONTROLLER] = condition_test_control_group_controller, -- [CONDITION_NULL] = condition_test_null, - [CONDITION_CPUS] = condition_test_cpus, - [CONDITION_MEMORY] = condition_test_memory, - [CONDITION_ENVIRONMENT] = condition_test_environment, -@@ -859,23 +849,20 @@ bool condition_test_list( - r = condition_test(c, env); - - if (logger) { -- const char *p = c->type == CONDITION_NULL ? "true" : c->parameter; -- assert(p); -- - if (r < 0) - logger(userdata, LOG_WARNING, r, PROJECT_FILE, __LINE__, __func__, - "Couldn't determine result for %s=%s%s%s, assuming failed: %m", - to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", -- p); -+ c->parameter); - else - logger(userdata, LOG_DEBUG, 0, PROJECT_FILE, __LINE__, __func__, - "%s=%s%s%s %s.", - to_string(c->type), - c->trigger ? "|" : "", - c->negate ? "!" : "", -- p, -+ c->parameter, - condition_result_to_string(c->result)); - } - -@@ -937,7 +924,6 @@ static const char* const condition_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_USER] = "ConditionUser", - [CONDITION_GROUP] = "ConditionGroup", - [CONDITION_CONTROL_GROUP_CONTROLLER] = "ConditionControlGroupController", -- [CONDITION_NULL] = "ConditionNull", - [CONDITION_CPUS] = "ConditionCPUs", - [CONDITION_MEMORY] = "ConditionMemory", - [CONDITION_ENVIRONMENT] = "ConditionEnvironment", -@@ -969,7 +955,6 @@ static const char* const assert_type_table[_CONDITION_TYPE_MAX] = { - [CONDITION_USER] = "AssertUser", - [CONDITION_GROUP] = "AssertGroup", - [CONDITION_CONTROL_GROUP_CONTROLLER] = "AssertControlGroupController", -- [CONDITION_NULL] = "AssertNull", - [CONDITION_CPUS] = "AssertCPUs", - [CONDITION_MEMORY] = "AssertMemory", - [CONDITION_ENVIRONMENT] = "AssertEnvironment", -diff --git a/src/shared/condition.h b/src/shared/condition.h -index fea74d228d8..e5ad43f945b 100644 ---- a/src/shared/condition.h -+++ b/src/shared/condition.h -@@ -34,8 +34,6 @@ typedef enum ConditionType { - CONDITION_FILE_NOT_EMPTY, - CONDITION_FILE_IS_EXECUTABLE, - -- CONDITION_NULL, -- - CONDITION_USER, - CONDITION_GROUP, - -diff --git a/src/test/test-condition.c b/src/test/test-condition.c -index ddf2e669c03..d209c1304c8 100644 ---- a/src/test/test-condition.c -+++ b/src/test/test-condition.c -@@ -438,20 +438,6 @@ static void test_condition_test_kernel_version(void) { - condition_free(condition); - } - --static void test_condition_test_null(void) { -- Condition *condition; -- -- condition = condition_new(CONDITION_NULL, NULL, false, false); -- assert_se(condition); -- assert_se(condition_test(condition, environ) > 0); -- condition_free(condition); -- -- condition = condition_new(CONDITION_NULL, NULL, false, true); -- assert_se(condition); -- assert_se(condition_test(condition, environ) == 0); -- condition_free(condition); --} -- - static void test_condition_test_security(void) { - Condition *condition; - -@@ -868,7 +854,6 @@ int main(int argc, char *argv[]) { - test_condition_test_architecture(); - test_condition_test_kernel_command_line(); - test_condition_test_kernel_version(); -- test_condition_test_null(); - test_condition_test_security(); - print_securities(); - test_condition_test_virtualization(); -diff --git a/test/fuzz/fuzz-unit-file/systemd-machined.service b/test/fuzz/fuzz-unit-file/systemd-machined.service -index 70b627c5f40..79ee9861d8e 100644 ---- a/test/fuzz/fuzz-unit-file/systemd-machined.service -+++ b/test/fuzz/fuzz-unit-file/systemd-machined.service -@@ -15,9 +15,6 @@ Documentation=https://www.freedesktop.org/wiki/Software/systemd/machined - Wants=machine.slice - After=machine.slice - RequiresMountsFor=/var/lib/machines --ConditionNull=true --ConditionNull= --ConditionNull=|!false - OnFailureIsolate=false - FailureActionExitStatus=222 - FailureActionExitStatus= diff --git a/SOURCES/16838_16857_improve_path_search.patch b/SOURCES/16838_16857_improve_path_search.patch deleted file mode 100644 index 2120465..0000000 --- a/SOURCES/16838_16857_improve_path_search.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 3335de91437bc983c95cfab86489ceb3a0b0a6aa Mon Sep 17 00:00:00 2001 -From: Chris Down -Date: Tue, 25 Aug 2020 21:59:11 +0100 -Subject: [PATCH 1/2] path: Skip directories when finalising $PATH search - -Imagine $PATH /a:/b. There is an echo command at /b/echo. Under this -configuration, this works fine: - - % systemd-run --user --scope echo . - Running scope as unit: run-rfe98e0574b424d63a641644af511ff30.scope - . - -However, if I do `mkdir /a/echo`, this happens: - - % systemd-run --user --scope echo . - Running scope as unit: run-rcbe9369537ed47f282ee12ce9f692046.scope - Failed to execute: Permission denied - -We check whether the resulting file is executable for the performing -user, but of course, most directories are anyway, since that's needed to -list within it. As such, another is_dir() check is needed prior to -considering the search result final. - -Another approach might be to check S_ISREG, but there may be more gnarly -edge cases there than just eliminating this obviously pathological -example, so let's just do this for now. ---- - src/basic/path-util.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/src/basic/path-util.c b/src/basic/path-util.c -index c4e022b3a1..d3b4978239 100644 ---- a/src/basic/path-util.c -+++ b/src/basic/path-util.c -@@ -637,6 +637,9 @@ int find_binary(const char *name, char **ret) { - if (!j) - return -ENOMEM; - -+ if (is_dir(j, true)) -+ continue; -+ - if (access(j, X_OK) >= 0) { - /* Found it! */ - --- -2.26.2 - - -From 2f94890f37c13dcd680a63876ed6d34f8e66d0a3 Mon Sep 17 00:00:00 2001 -From: Chris Down -Date: Wed, 26 Aug 2020 18:49:27 +0100 -Subject: [PATCH 2/2] path: Improve $PATH search directory case - -Previously: - -1. last_error wouldn't be updated with errors from is_dir; -2. We'd always issue a stat(), even for binaries without execute; -3. We used stat() instead of access(), which is cheaper. - -This change avoids all of those, by only checking inside X_OK-positive -case whether access() works on the path with an extra slash appended. -Thanks to Lennart for the suggestion. ---- - src/basic/path-util.c | 25 ++++++++++++++++++------- - 1 file changed, 18 insertions(+), 7 deletions(-) - -diff --git a/src/basic/path-util.c b/src/basic/path-util.c -index d3b4978239..7b0863f749 100644 ---- a/src/basic/path-util.c -+++ b/src/basic/path-util.c -@@ -637,16 +637,27 @@ int find_binary(const char *name, char **ret) { - if (!j) - return -ENOMEM; - -- if (is_dir(j, true)) -- continue; -- - if (access(j, X_OK) >= 0) { -- /* Found it! */ -+ _cleanup_free_ char *with_dash; - -- if (ret) -- *ret = path_simplify(TAKE_PTR(j), false); -+ with_dash = strjoin(j, "/"); -+ if (!with_dash) -+ return -ENOMEM; - -- return 0; -+ /* If this passes, it must be a directory, and so should be skipped. */ -+ if (access(with_dash, X_OK) >= 0) -+ continue; -+ -+ /** -+ * We can't just `continue` inverting this case, since we need to update last_error. -+ */ -+ if (errno == ENOTDIR) { -+ /* Found it! */ -+ if (ret) -+ *ret = path_simplify(TAKE_PTR(j), false); -+ -+ return 0; -+ } - } - - /* PATH entries which we don't have access to are ignored, as per tradition. */ --- -2.26.2 - diff --git a/SOURCES/16940_cleanup_socket_econn_handling.patch b/SOURCES/16940_cleanup_socket_econn_handling.patch deleted file mode 100644 index 3de1ab0..0000000 --- a/SOURCES/16940_cleanup_socket_econn_handling.patch +++ /dev/null @@ -1,317 +0,0 @@ -From 056799e2e147d678e156c5a1fce15b04762f1313 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Tue, 1 Sep 2020 23:50:01 +0200 -Subject: [PATCH 1/3] core/socket: we may get ENOTCONN from - socket_instantiate_service() - -This means that the connection was aborted before we even got to figure out -what the service name will be. Let's treat this as a non-event and close the -connection fd without any further messages. - -Code last changed in 934ef6a5. -Reported-by: Thiago Macieira - -With the patch: -systemd[1]: foobar.socket: Incoming traffic -systemd[1]: foobar.socket: Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring. -... - -Also, when we get ENOMEM, don't give the hint about missing unit. ---- - src/core/socket.c | 35 ++++++++++++++++++++++++----------- - 1 file changed, 24 insertions(+), 11 deletions(-) - -diff --git a/src/core/socket.c b/src/core/socket.c -index ebf5ce3b16..f880040331 100644 ---- a/src/core/socket.c -+++ b/src/core/socket.c -@@ -18,6 +18,7 @@ - #include "dbus-socket.h" - #include "dbus-unit.h" - #include "def.h" -+#include "errno-list.h" - #include "exit-status.h" - #include "fd-util.h" - #include "format-util.h" -@@ -1418,11 +1419,12 @@ int socket_load_service_unit(Socket *s, int cfd, Unit **ret) { - - if (cfd >= 0) { - r = instance_from_socket(cfd, s->n_accepted, &instance); -- if (r == -ENOTCONN) -- /* ENOTCONN is legitimate if TCP RST was received. -- * This connection is over, but the socket unit lives on. */ -+ if (ERRNO_IS_DISCONNECT(r)) -+ /* ENOTCONN is legitimate if TCP RST was received. Other socket families might return -+ * different errors. This connection is over, but the socket unit lives on. */ - return log_unit_debug_errno(UNIT(s), r, -- "Got ENOTCONN on incoming socket, assuming aborted connection attempt, ignoring."); -+ "Got %s on incoming socket, assuming aborted connection attempt, ignoring.", -+ errno_to_name(r)); - if (r < 0) - return r; - } -@@ -2359,8 +2361,8 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (!pending) { - if (!UNIT_ISSET(s->service)) { -- log_unit_error(UNIT(s), "Service to activate vanished, refusing activation."); -- r = -ENOENT; -+ r = log_unit_error_errno(UNIT(s), SYNTHETIC_ERRNO(ENOENT), -+ "Service to activate vanished, refusing activation."); - goto fail; - } - -@@ -2382,8 +2384,10 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (s->max_connections_per_source > 0) { - r = socket_acquire_peer(s, cfd, &p); -- if (r < 0) -- goto refuse; -+ if (ERRNO_IS_DISCONNECT(r)) -+ goto notconn; -+ if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */ -+ goto fail; - if (r > 0 && p->n_ref > s->max_connections_per_source) { - _cleanup_free_ char *t = NULL; - -@@ -2397,6 +2401,8 @@ static void socket_enter_running(Socket *s, int cfd) { - } - - r = socket_instantiate_service(s, cfd); -+ if (ERRNO_IS_DISCONNECT(r)) -+ goto notconn; - if (r < 0) - goto fail; - -@@ -2406,6 +2412,8 @@ static void socket_enter_running(Socket *s, int cfd) { - s->n_accepted++; - - r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); -+ if (ERRNO_IS_DISCONNECT(r)) -+ goto notconn; - if (r < 0) - goto fail; - -@@ -2430,13 +2438,18 @@ static void socket_enter_running(Socket *s, int cfd) { - - refuse: - s->n_refused++; -+notconn: - safe_close(cfd); - return; - - fail: -- log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", -- cfd >= 0 ? "template" : "non-template", -- bus_error_message(&error, r)); -+ if (ERRNO_IS_RESOURCE(r)) -+ log_unit_warning(UNIT(s), "Failed to queue service startup job: %s", -+ bus_error_message(&error, r)); -+ else -+ log_unit_warning(UNIT(s), "Failed to queue service startup job (Maybe the service file is missing or not a %s unit?): %s", -+ cfd >= 0 ? "template" : "non-template", -+ bus_error_message(&error, r)); - - socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); - safe_close(cfd); --- -2.26.2 - - -From 86f9af3eb8bea0bea86bb027cb341e6b13beecb5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 2 Sep 2020 18:04:10 +0200 -Subject: [PATCH 2/3] core/socket: fold socket_instantiate_service() into - socket_enter_running() - -socket_instantiate_service() was doing unit_ref_set(), and the caller was -immediately doing unit_ref_unset(). After we get rid of this, it doesn't seem -worth it to have two functions. ---- - src/core/socket.c | 39 ++++++++++----------------------------- - 1 file changed, 10 insertions(+), 29 deletions(-) - -diff --git a/src/core/socket.c b/src/core/socket.c -index f880040331..5e128d9fef 100644 ---- a/src/core/socket.c -+++ b/src/core/socket.c -@@ -206,27 +206,6 @@ static int socket_arm_timer(Socket *s, usec_t usec) { - return 0; - } - --static int socket_instantiate_service(Socket *s, int cfd) { -- Unit *service; -- int r; -- -- assert(s); -- assert(cfd >= 0); -- -- /* This fills in s->service if it isn't filled in yet. For Accept=yes sockets we create the next -- * connection service here. For Accept=no this is mostly a NOP since the service is figured out at -- * load time anyway. */ -- -- r = socket_load_service_unit(s, cfd, &service); -- if (r < 0) -- return r; -- -- unit_ref_set(&s->service, UNIT(s), service); -- -- return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service, -- false, UNIT_DEPENDENCY_IMPLICIT); --} -- - static bool have_non_accept_socket(Socket *s) { - SocketPort *p; - -@@ -2374,7 +2353,7 @@ static void socket_enter_running(Socket *s, int cfd) { - socket_set_state(s, SOCKET_RUNNING); - } else { - _cleanup_(socket_peer_unrefp) SocketPeer *p = NULL; -- Service *service; -+ Unit *service; - - if (s->n_connections >= s->max_connections) { - log_unit_warning(UNIT(s), "Too many incoming connections (%u), dropping connection.", -@@ -2400,18 +2379,20 @@ static void socket_enter_running(Socket *s, int cfd) { - } - } - -- r = socket_instantiate_service(s, cfd); -+ r = socket_load_service_unit(s, cfd, &service); - if (ERRNO_IS_DISCONNECT(r)) - goto notconn; - if (r < 0) - goto fail; - -- service = SERVICE(UNIT_DEREF(s->service)); -- unit_ref_unset(&s->service); -+ r = unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, service, -+ false, UNIT_DEPENDENCY_IMPLICIT); -+ if (r < 0) -+ goto fail; - - s->n_accepted++; - -- r = service_set_socket_fd(service, cfd, s, s->selinux_context_from_net); -+ r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net); - if (ERRNO_IS_DISCONNECT(r)) - goto notconn; - if (r < 0) -@@ -2420,13 +2401,13 @@ static void socket_enter_running(Socket *s, int cfd) { - TAKE_FD(cfd); /* We passed ownership of the fd to the service now. Forget it here. */ - s->n_connections++; - -- service->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */ -+ SERVICE(service)->peer = TAKE_PTR(p); /* Pass ownership of the peer reference */ - -- r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT(service), JOB_REPLACE, NULL, &error, NULL); -+ r = manager_add_job(UNIT(s)->manager, JOB_START, service, JOB_REPLACE, NULL, &error, NULL); - if (r < 0) { - /* We failed to activate the new service, but it still exists. Let's make sure the - * service closes and forgets the connection fd again, immediately. */ -- service_close_socket_fd(service); -+ service_close_socket_fd(SERVICE(service)); - goto fail; - } - --- -2.26.2 - - -From b7e9403a4c6220478980555ef40905d030b307f5 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= -Date: Wed, 2 Sep 2020 18:17:14 +0200 -Subject: [PATCH 3/3] core/socket: use _cleanup_ to close the connection fd - -Removing the gotos would lead to a lot of duplicated code, so I left them -as they were. ---- - src/core/socket.c | 22 ++++++++++------------ - 1 file changed, 10 insertions(+), 12 deletions(-) - -diff --git a/src/core/socket.c b/src/core/socket.c -index 5e128d9fef..a77a297cf5 100644 ---- a/src/core/socket.c -+++ b/src/core/socket.c -@@ -2296,13 +2296,14 @@ static void flush_ports(Socket *s) { - } - } - --static void socket_enter_running(Socket *s, int cfd) { -+static void socket_enter_running(Socket *s, int cfd_in) { -+ /* Note that this call takes possession of the connection fd passed. It either has to assign it -+ * somewhere or close it. */ -+ _cleanup_close_ int cfd = cfd_in; -+ - _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; - int r; - -- /* Note that this call takes possession of the connection fd passed. It either has to assign it somewhere or -- * close it. */ -- - assert(s); - - /* We don't take connections anymore if we are supposed to shut down anyway */ -@@ -2312,9 +2313,8 @@ static void socket_enter_running(Socket *s, int cfd) { - - if (cfd >= 0) - goto refuse; -- else -- flush_ports(s); - -+ flush_ports(s); - return; - } - -@@ -2364,7 +2364,7 @@ static void socket_enter_running(Socket *s, int cfd) { - if (s->max_connections_per_source > 0) { - r = socket_acquire_peer(s, cfd, &p); - if (ERRNO_IS_DISCONNECT(r)) -- goto notconn; -+ return; - if (r < 0) /* We didn't have enough resources to acquire peer information, let's fail. */ - goto fail; - if (r > 0 && p->n_ref > s->max_connections_per_source) { -@@ -2381,7 +2381,7 @@ static void socket_enter_running(Socket *s, int cfd) { - - r = socket_load_service_unit(s, cfd, &service); - if (ERRNO_IS_DISCONNECT(r)) -- goto notconn; -+ return; - if (r < 0) - goto fail; - -@@ -2394,7 +2394,7 @@ static void socket_enter_running(Socket *s, int cfd) { - - r = service_set_socket_fd(SERVICE(service), cfd, s, s->selinux_context_from_net); - if (ERRNO_IS_DISCONNECT(r)) -- goto notconn; -+ return; - if (r < 0) - goto fail; - -@@ -2415,12 +2415,11 @@ static void socket_enter_running(Socket *s, int cfd) { - unit_add_to_dbus_queue(UNIT(s)); - } - -+ TAKE_FD(cfd); - return; - - refuse: - s->n_refused++; --notconn: -- safe_close(cfd); - return; - - fail: -@@ -2433,7 +2432,6 @@ fail: - bus_error_message(&error, r)); - - socket_enter_stop_pre(s, SOCKET_FAILURE_RESOURCES); -- safe_close(cfd); - } - - static void socket_run_next(Socket *s) { --- -2.26.2 - diff --git a/SOURCES/17031_propagate_start_limit_hit.patch b/SOURCES/17031_propagate_start_limit_hit.patch deleted file mode 100644 index 4490100..0000000 --- a/SOURCES/17031_propagate_start_limit_hit.patch +++ /dev/null @@ -1,233 +0,0 @@ -From 7a481a17ad01c7be526829a835f7da3d6b71577f Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Fri, 11 Sep 2020 19:49:33 +0200 -Subject: [PATCH 1/3] core: propagate triggered unit in more load states - -In 4c2ef3276735ad9f7fccf33f5bdcbe7d8751e7ec we enabled propagating -triggered unit state to the triggering unit for service units in more -load states, so that we don't accidentally stop tracking state -correctly. - -Do the same for our other triggering unit states: automounts, paths, and -timers. - -Also, make this an assertion rather than a simple test. After all it -should never happen that we get called for half-loaded units or units of -the wrong type. The load routines should already have made this -impossible. ---- - src/core/automount.c | 4 ++-- - src/core/path.c | 7 +++---- - src/core/socket.c | 9 ++------- - src/core/timer.c | 4 ++-- - src/core/transaction.c | 2 +- - src/core/unit.h | 4 ++++ - 6 files changed, 14 insertions(+), 16 deletions(-) - -diff --git a/src/core/automount.c b/src/core/automount.c -index 1f05198766..73f0fb8c71 100644 ---- a/src/core/automount.c -+++ b/src/core/automount.c -@@ -507,8 +507,8 @@ static void automount_trigger_notify(Unit *u, Unit *other) { - assert(other); - - /* Filter out invocations with bogus state */ -- if (other->load_state != UNIT_LOADED || other->type != UNIT_MOUNT) -- return; -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); -+ assert(other->type == UNIT_MOUNT); - - /* Don't propagate state changes from the mount if we are already down */ - if (!IN_SET(a->state, AUTOMOUNT_WAITING, AUTOMOUNT_RUNNING)) -diff --git a/src/core/path.c b/src/core/path.c -index 1c3c28e341..8ffec72ede 100644 ---- a/src/core/path.c -+++ b/src/core/path.c -@@ -748,11 +748,10 @@ static void path_trigger_notify(Unit *u, Unit *other) { - assert(u); - assert(other); - -- /* Invoked whenever the unit we trigger changes state or gains -- * or loses a job */ -+ /* Invoked whenever the unit we trigger changes state or gains or loses a job */ - -- if (other->load_state != UNIT_LOADED) -- return; -+ /* Filter out invocations with bogus state */ -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); - - if (p->state == PATH_RUNNING && - UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { -diff --git a/src/core/socket.c b/src/core/socket.c -index 127195c9fe..ebf5ce3b16 100644 ---- a/src/core/socket.c -+++ b/src/core/socket.c -@@ -3274,13 +3274,8 @@ static void socket_trigger_notify(Unit *u, Unit *other) { - assert(other); - - /* Filter out invocations with bogus state */ -- if (!IN_SET(other->load_state, -- UNIT_LOADED, -- UNIT_NOT_FOUND, -- UNIT_BAD_SETTING, -- UNIT_ERROR, -- UNIT_MASKED) || other->type != UNIT_SERVICE) -- return; -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); -+ assert(other->type == UNIT_SERVICE); - - /* Don't propagate state changes from the service if we are already down */ - if (!IN_SET(s->state, SOCKET_RUNNING, SOCKET_LISTENING)) -diff --git a/src/core/timer.c b/src/core/timer.c -index 03a9c14f76..94388f0727 100644 ---- a/src/core/timer.c -+++ b/src/core/timer.c -@@ -746,8 +746,8 @@ static void timer_trigger_notify(Unit *u, Unit *other) { - assert(u); - assert(other); - -- if (other->load_state != UNIT_LOADED) -- return; -+ /* Filter out invocations with bogus state */ -+ assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); - - /* Reenable all timers that depend on unit state */ - LIST_FOREACH(value, v, t->values) -diff --git a/src/core/transaction.c b/src/core/transaction.c -index 0fa419787e..befac19788 100644 ---- a/src/core/transaction.c -+++ b/src/core/transaction.c -@@ -949,7 +949,7 @@ int transaction_add_job_and_dependencies( - - /* Safety check that the unit is a valid state, i.e. not in UNIT_STUB or UNIT_MERGED which should only be set - * temporarily. */ -- if (!IN_SET(unit->load_state, UNIT_LOADED, UNIT_ERROR, UNIT_NOT_FOUND, UNIT_BAD_SETTING, UNIT_MASKED)) -+ if (!UNIT_IS_LOAD_COMPLETE(unit->load_state)) - return sd_bus_error_setf(e, BUS_ERROR_LOAD_FAILED, "Unit %s is not loaded properly.", unit->id); - - if (type != JOB_STOP) { -diff --git a/src/core/unit.h b/src/core/unit.h -index 4130cd50a9..ae2ce74243 100644 ---- a/src/core/unit.h -+++ b/src/core/unit.h -@@ -49,6 +49,10 @@ static inline bool UNIT_IS_INACTIVE_OR_FAILED(UnitActiveState t) { - return IN_SET(t, UNIT_INACTIVE, UNIT_FAILED); - } - -+static inline bool UNIT_IS_LOAD_COMPLETE(UnitLoadState t) { -+ return t >= 0 && t < _UNIT_LOAD_STATE_MAX && t != UNIT_STUB && t != UNIT_MERGED; -+} -+ - /* Stores the 'reason' a dependency was created as a bit mask, i.e. due to which configuration source it came to be. We - * use this so that we can selectively flush out parts of dependencies again. Note that the same dependency might be - * created as a result of multiple "reasons", hence the bitmask. */ --- -2.26.2 - - -From 6b083e21c2bfdba79d43d5d56f02dc795dae9368 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Fri, 11 Sep 2020 19:57:09 +0200 -Subject: [PATCH 2/3] core: propagate unit start limit hit state to triggering - path unit - -We already do this for socket and automount units, do it for path units -too: if the triggered service keeps hitting the start limit, then fail -the triggering unit too, so that we don#t busy loop forever. - -(Note that this leaves only timer units out in the cold for this kind of -protection, but it shouldn't matter there, as they are naturally -protected against busy loops: they are scheduled by time anyway). - -Fixes: #16669 ---- - src/core/path.c | 15 +++++++++++++++ - src/core/path.h | 1 + - 2 files changed, 16 insertions(+) - -diff --git a/src/core/path.c b/src/core/path.c -index 8ffec72ede..4f4e7100cf 100644 ---- a/src/core/path.c -+++ b/src/core/path.c -@@ -753,6 +753,20 @@ static void path_trigger_notify(Unit *u, Unit *other) { - /* Filter out invocations with bogus state */ - assert(UNIT_IS_LOAD_COMPLETE(other->load_state)); - -+ /* Don't propagate state changes from the triggered unit if we are already down */ -+ if (!IN_SET(p->state, PATH_WAITING, PATH_RUNNING)) -+ return; -+ -+ /* Propagate start limit hit state */ -+ if (other->start_limit_hit) { -+ path_enter_dead(p, PATH_FAILURE_UNIT_START_LIMIT_HIT); -+ return; -+ } -+ -+ /* Don't propagate anything if there's still a job queued */ -+ if (other->job) -+ return; -+ - if (p->state == PATH_RUNNING && - UNIT_IS_INACTIVE_OR_FAILED(unit_active_state(other))) { - log_unit_debug(UNIT(p), "Got notified about unit deactivation."); -@@ -789,6 +803,7 @@ static const char* const path_result_table[_PATH_RESULT_MAX] = { - [PATH_SUCCESS] = "success", - [PATH_FAILURE_RESOURCES] = "resources", - [PATH_FAILURE_START_LIMIT_HIT] = "start-limit-hit", -+ [PATH_FAILURE_UNIT_START_LIMIT_HIT] = "unit-start-limit-hit", - }; - - DEFINE_STRING_TABLE_LOOKUP(path_result, PathResult); -diff --git a/src/core/path.h b/src/core/path.h -index 9e2836535a..4043650fe0 100644 ---- a/src/core/path.h -+++ b/src/core/path.h -@@ -45,6 +45,7 @@ typedef enum PathResult { - PATH_SUCCESS, - PATH_FAILURE_RESOURCES, - PATH_FAILURE_START_LIMIT_HIT, -+ PATH_FAILURE_UNIT_START_LIMIT_HIT, - _PATH_RESULT_MAX, - _PATH_RESULT_INVALID = -1 - } PathResult; --- -2.26.2 - - -From 32c556c612ff38b09fe7d14d1840aceb2d76360d Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Mon, 14 Sep 2020 12:59:38 +0200 -Subject: [PATCH 3/3] unit-def: drop pointless 0 initialization of first enum - value - -This is implied in C and we generally don't bother with this, so don't -bother with this here either. ---- - src/basic/unit-def.h | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h -index 53419ecd8a..1fab6c78ab 100644 ---- a/src/basic/unit-def.h -+++ b/src/basic/unit-def.h -@@ -9,7 +9,7 @@ - * when other criteria (cpu weight, nice level) are identical. - * In this case service units have the highest priority. */ - typedef enum UnitType { -- UNIT_SERVICE = 0, -+ UNIT_SERVICE, - UNIT_MOUNT, - UNIT_SWAP, - UNIT_SOCKET, -@@ -25,7 +25,7 @@ typedef enum UnitType { - } UnitType; - - typedef enum UnitLoadState { -- UNIT_STUB = 0, -+ UNIT_STUB, - UNIT_LOADED, - UNIT_NOT_FOUND, /* error condition #1: unit file not found */ - UNIT_BAD_SETTING, /* error condition #2: we couldn't parse some essential unit file setting */ --- -2.26.2 - diff --git a/SOURCES/17082_nspawn_tty_tweaks.patch b/SOURCES/17082_nspawn_tty_tweaks.patch deleted file mode 100644 index adee19a..0000000 --- a/SOURCES/17082_nspawn_tty_tweaks.patch +++ /dev/null @@ -1,316 +0,0 @@ -From 0ead15331dc9414e7d4b3f0b96ed1908ceaf8f8b Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Wed, 16 Sep 2020 22:11:48 +0200 -Subject: [PATCH 1/5] nspawn: check return of setsid() - -Let's verify that everything works the way we expect it to work, hence -check setsid() return code. ---- - src/nspawn/nspawn-stub-pid1.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c -index d86dd23185..f785a3b248 100644 ---- a/src/nspawn/nspawn-stub-pid1.c -+++ b/src/nspawn/nspawn-stub-pid1.c -@@ -66,7 +66,10 @@ int stub_pid1(sd_id128_t uuid) { - if (pid == 0) { - /* Return in the child */ - assert_se(sigprocmask(SIG_SETMASK, &oldmask, NULL) >= 0); -- setsid(); -+ -+ if (setsid() < 0) -+ return log_error_errno(errno, "Failed to become session leader in payload process: %m"); -+ - return 0; - } - --- -2.26.2 - - -From b4fa908fbdcbcf01c96e983460689800b8bb76af Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Wed, 16 Sep 2020 22:12:29 +0200 -Subject: [PATCH 2/5] nspawn: print log notice when we are invoked from a tty - but in "pipe" mode - -If people do this then things are weird, and they should probably use ---console=interactive (i.e. the default) instead. - -Prompted-by: #17070 ---- - src/nspawn/nspawn.c | 10 ++++++++-- - 1 file changed, 8 insertions(+), 2 deletions(-) - -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index 3b9493f232..efc541f512 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -272,9 +272,15 @@ static int handle_arg_console(const char *arg) { - arg_console_mode = CONSOLE_READ_ONLY; - else if (streq(arg, "passive")) - arg_console_mode = CONSOLE_PASSIVE; -- else if (streq(arg, "pipe")) -+ else if (streq(arg, "pipe")) { -+ if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0) -+ log_full(arg_quiet ? LOG_DEBUG : LOG_NOTICE, -+ "Console mode 'pipe' selected, but standard input/output are connected to an interactive TTY. " -+ "Most likely you want to use 'interactive' console mode for proper interactivity and shell job control. " -+ "Proceeding anyway."); -+ - arg_console_mode = CONSOLE_PIPE; -- else -+ } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg); - - arg_settings_mask |= SETTING_CONSOLE_MODE; --- -2.26.2 - - -From 19db1706dadcec4f4c44f9abf8dc33a336f93326 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Wed, 16 Sep 2020 22:16:10 +0200 -Subject: [PATCH 3/5] nspawn: fix fd leak on failure path - ---- - src/nspawn/nspawn.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index efc541f512..15dbdbe738 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -2178,7 +2178,7 @@ static int setup_pts(const char *dest) { - } - - static int setup_stdio_as_dev_console(void) { -- int terminal; -+ _cleanup_close_ int terminal = -1; - int r; - - terminal = open_terminal("/dev/console", O_RDWR); -@@ -2193,6 +2193,7 @@ static int setup_stdio_as_dev_console(void) { - - /* invalidates 'terminal' on success and failure */ - r = rearrange_stdio(terminal, terminal, terminal); -+ TAKE_FD(terminal); - if (r < 0) - return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m"); - --- -2.26.2 - - -From d297a871ef720227af845fe8b0f1e0fe7560b433 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Wed, 16 Sep 2020 22:34:43 +0200 -Subject: [PATCH 4/5] nspawn: don't become TTY controller just to undo it later - again - -Instead of first becoming a controlling process of the payload pty -as side effect of opening it (without O_NOCTTY), and then possibly -dropping it again, let's do it cleanly an reverse the logic: let's open -the pty without becoming its controller first. Only after everything -went the way we wanted it to go become the controller explicitly. - -This has the benefit that the PID 1 stub process we run (as effect of ---as-pid2) doesn't have to lose the tty explicitly, but can just -continue running with things. And we explicitly make the tty controlling -right before invoking actual payload. - -In order to make sure everything works as expected validate that the -stub PID 1 in the container really has no conrolling tty by issuing the -TIOCNOTTY tty and expecting ENOTTY, and log about it. - -This shouldn't change behaviour much, it just makes thins a bit cleaner, -in particular as we'll not trigger SIGHUP on ourselves (since we are -controller and session leader) due to TIOCNOTTY which we then have to -explicitly ignore. ---- - src/nspawn/nspawn-stub-pid1.c | 12 ++++++------ - src/nspawn/nspawn.c | 16 +++++++++++++--- - 2 files changed, 19 insertions(+), 9 deletions(-) - -diff --git a/src/nspawn/nspawn-stub-pid1.c b/src/nspawn/nspawn-stub-pid1.c -index f785a3b248..60d7439fb1 100644 ---- a/src/nspawn/nspawn-stub-pid1.c -+++ b/src/nspawn/nspawn-stub-pid1.c -@@ -53,12 +53,6 @@ int stub_pid1(sd_id128_t uuid) { - assert_se(sigfillset(&fullmask) >= 0); - assert_se(sigprocmask(SIG_BLOCK, &fullmask, &oldmask) >= 0); - -- /* Surrender the terminal this stub may control so that child processes can have a controlling terminal -- * without resorting to setsid hacks. */ -- r = ioctl(STDIN_FILENO, TIOCNOTTY); -- if (r < 0 && errno != ENOTTY) -- return log_error_errno(errno, "Failed to surrender controlling terminal: %m"); -- - pid = fork(); - if (pid < 0) - return log_error_errno(errno, "Failed to fork child pid: %m"); -@@ -79,6 +73,12 @@ int stub_pid1(sd_id128_t uuid) { - (void) close_all_fds(NULL, 0); - log_open(); - -+ if (ioctl(STDIN_FILENO, TIOCNOTTY) < 0) { -+ if (errno != ENOTTY) -+ log_warning_errno(errno, "Unexpected error from TIOCNOTTY ioctl in init stub process, ignoring: %m"); -+ } else -+ log_warning("Expected TIOCNOTTY to fail, but it succeeded in init stub process, ignoring."); -+ - /* Flush out /proc/self/environ, so that we don't leak the environment from the host into the container. Also, - * set $container= and $container_uuid= so that clients in the container that query it from /proc/1/environ - * find them set. */ -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index 15dbdbe738..783147f122 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -11,10 +11,12 @@ - #endif - #include - #include -+#include - #include - #include - #include - #include -+#include - #include - - #include "sd-bus.h" -@@ -2181,7 +2183,9 @@ static int setup_stdio_as_dev_console(void) { - _cleanup_close_ int terminal = -1; - int r; - -- terminal = open_terminal("/dev/console", O_RDWR); -+ /* We open the TTY in O_NOCTTY mode, so that we do not become controller yet. We'll do that later -+ * explicitly, if we are configured to. */ -+ terminal = open_terminal("/dev/console", O_RDWR|O_NOCTTY); - if (terminal < 0) - return log_error_errno(terminal, "Failed to open console: %m"); - -@@ -3213,8 +3217,7 @@ static int inner_child( - * wait until the parent is ready with the - * setup, too... */ - if (!barrier_place_and_sync(barrier)) /* #5 */ -- return log_error_errno(SYNTHETIC_ERRNO(ESRCH), -- "Parent died too early"); -+ return log_error_errno(SYNTHETIC_ERRNO(ESRCH), "Parent died too early"); - - if (arg_chdir) - if (chdir(arg_chdir) < 0) -@@ -3226,6 +3229,13 @@ static int inner_child( - return r; - } - -+ if (arg_console_mode != CONSOLE_PIPE) { -+ /* So far our pty wasn't controlled by any process. Finally, it's time to change that, if we -+ * are configured for that. Acquire it as controlling tty. */ -+ if (ioctl(STDIN_FILENO, TIOCSCTTY) < 0) -+ return log_error_errno(errno, "Failed to acquire controlling TTY: %m"); -+ } -+ - log_debug("Inner child completed, invoking payload."); - - /* Now, explicitly close the log, so that we then can close all remaining fds. Closing the log explicitly first --- -2.26.2 - - -From 196b94c2db3f0b763480e98df98f288bcd044a6e Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Thu, 17 Sep 2020 16:26:14 +0200 -Subject: [PATCH 5/5] nspawn: add --console=autopipe mode - -By default we'll run a container in --console=interactive and ---console=read-only mode depending if we are invoked on a tty or not so -that the container always gets a /dev/console allocated, i.e is always -suitable to run a full init system /as those typically expect a -/dev/console to exist). - -With the new --console=autopipe mode we do something similar, but -slightly different: when not invoked on a tty we'll use --console=pipe. -This means, if you invoke some tool in a container with this you'll get -full inetractivity if you invoke it on a tty but things will also be -very nicely pipeable. OTOH you cannot invoke a full init system like -this, because you might or might not become a /dev/console this way... - -Prompted-by: #17070 - -(I named this "autopipe" rather than "auto" or so, since the default -mode probably should be named "auto" one day if we add a name for it, -and this is so similar to "auto" except that it uses pipes in the -non-tty case). ---- - man/systemd-nspawn.xml | 21 ++++++++++++--------- - src/nspawn/nspawn.c | 12 +++++++++--- - 2 files changed, 21 insertions(+), 12 deletions(-) - -diff --git a/man/systemd-nspawn.xml b/man/systemd-nspawn.xml -index 69558ac85c..b2c2a5006c 100644 ---- a/man/systemd-nspawn.xml -+++ b/man/systemd-nspawn.xml -@@ -1370,15 +1370,18 @@ - - Configures how to set up standard input, output and error output for the container - payload, as well as the /dev/console device for the container. Takes one of -- , , , or -- . If , a pseudo-TTY is allocated and made available -- as /dev/console in the container. It is then bi-directionally connected to the -- standard input and output passed to systemd-nspawn. is -- similar but only the output of the container is propagated and no input from the caller is read. If -- , a pseudo TTY is allocated, but it is not connected anywhere. Finally, in -- mode no pseudo TTY is allocated, but the standard input, output and error -- output file descriptors passed to systemd-nspawn are passed on — as they are — to -- the container payload, see the following paragraph. Defaults to if -+ , , , -+ or . If , a pseudo-TTY is -+ allocated and made available as /dev/console in the container. It is then -+ bi-directionally connected to the standard input and output passed to -+ systemd-nspawn. is similar but only the output of the -+ container is propagated and no input from the caller is read. If , a pseudo -+ TTY is allocated, but it is not connected anywhere. In mode no pseudo TTY is -+ allocated, but the standard input, output and error output file descriptors passed to -+ systemd-nspawn are passed on — as they are — to the container payload, see the -+ following paragraph. Finally, mode operates like -+ when systemd-nspawn is invoked on a terminal, and -+ like otherwise. Defaults to if - systemd-nspawn is invoked from a terminal, and - otherwise. - -diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c -index 783147f122..8837371232 100644 ---- a/src/nspawn/nspawn.c -+++ b/src/nspawn/nspawn.c -@@ -261,10 +261,11 @@ STATIC_DESTRUCTOR_REGISTER(arg_sysctl, strv_freep); - - static int handle_arg_console(const char *arg) { - if (streq(arg, "help")) { -- puts("interactive\n" -- "read-only\n" -+ puts("autopipe\n" -+ "interactive\n" - "passive\n" -- "pipe"); -+ "pipe\n" -+ "read-only"); - return 0; - } - -@@ -282,6 +283,11 @@ static int handle_arg_console(const char *arg) { - "Proceeding anyway."); - - arg_console_mode = CONSOLE_PIPE; -+ } else if (streq(arg, "autopipe")) { -+ if (isatty(STDIN_FILENO) > 0 && isatty(STDOUT_FILENO) > 0) -+ arg_console_mode = CONSOLE_INTERACTIVE; -+ else -+ arg_console_mode = CONSOLE_PIPE; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown console mode: %s", optarg); - --- -2.26.2 - diff --git a/SOURCES/17495.patch b/SOURCES/17495.patch new file mode 100644 index 0000000..fc6302c --- /dev/null +++ b/SOURCES/17495.patch @@ -0,0 +1,425 @@ +From 5adb2f01405d7cb7ba3cf9d4ee035f57952f79a6 Mon Sep 17 00:00:00 2001 +From: Chris Down +Date: Thu, 29 Oct 2020 12:03:52 +0000 +Subject: [PATCH 3/3] bpf: pid1: Pin reference to BPF programs for + post-coldplug +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +During `daemon-reload` and `daemon-reexec`, we detach and reattach all +BPF programs attached to cgroups. This, however, poses a real practical +problem for DevicePolicy (and some other settings using BPF): it +presents a period of time where the old device filtering BPF program has +been unloaded, but the new one has not been loaded yet. + +Since the filtering is at open() time, it has become apparent that that +there's a non-trivial period where applications inside that ostensibly +filtered cgroup can grab any device -- and often do so -- and then +retain access to that device even after the reload is over. Due to the +file continuing to be available after the initial open(), this issue is +particularly visible for DevicePolicy={strict,closed}, however it also +applies to other BPF programs we install. + +In particular, for BPF ingress/egress filtering this may have more +concerning implications: network traffic which is supposed to be +filtered will -- for a very brief period of time -- not be filtered or +subject to any restrictions imposed by BPF. + +These BPF programs are fundamentally attached to a cgroup lifetime, not +our unit lifetime, so it's enough to pin these programs by taking a +reference to affected BPF programs before reload/reexec. We can then +serialise the program's kernel-facing FD and cgroup attachment FD for +the new daemon, and have the daemon on the other side unpin the programs +after it's finished with coldplug. + +That means that, for example, the BPF program lifecycle during +daemon-reload or daemon-reexec changes from this: + + manager_clear_jobs_and_units + │ + ╔══════╪═════════╤═══════╗ + ║ prog │ no prog │ prog' ║ + ╚══════╧═════════╪═══════╝ + │ + manager_coldplug + +to this: + + manager_clear_jobs_and_units manager_dispatch_cgroup_realize_queue + │ │ + ╔══════╪═══════════════╤═══════════════════════╪═══════╗ + ║ prog │ prog (orphan) │ prog (orphan) + prog' │ prog' ║ + ╚══════╧═══════════════╪═══════════════════════╧═══════╝ + │ + manager_coldplug + +For daemon-reexec the semantics are mostly the same, but the point at +which the program becomes orphan is tied to the process lifecycle +instead. + +None of the BPF programs we install require exclusive access, so having +multiple instances of them running at the same time is fine. Custom +programs, of course, are unknown, but it's hard to imagine legitimate +cases which should be affected, whereas the benefits of this "overlap" +approach with reference pinning is immediately tangible. + +[keszybz: use _cleanup_ for unpin, use FOREACH_POINTER] +--- + src/core/bpf-firewall.c | 9 +-- + src/core/main.c | 9 +++ + src/core/manager.c | 161 ++++++++++++++++++++++++++++++++++++++- + src/core/manager.h | 6 ++ + src/shared/bpf-program.c | 10 +++ + src/shared/bpf-program.h | 1 + + 6 files changed, 189 insertions(+), 7 deletions(-) + +diff --git a/src/core/bpf-firewall.c b/src/core/bpf-firewall.c +index 99783aca22..c205ba1b19 100644 +--- a/src/core/bpf-firewall.c ++++ b/src/core/bpf-firewall.c +@@ -702,8 +702,7 @@ int bpf_firewall_install(Unit *u) { + if (r < 0) + return log_unit_error_errno(u, r, "Failed to determine cgroup path: %m"); + +- flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI && +- (u->type == UNIT_SLICE || unit_cgroup_delegate(u))) ? BPF_F_ALLOW_MULTI : 0; ++ flags = (supported == BPF_FIREWALL_SUPPORTED_WITH_MULTI) ? BPF_F_ALLOW_MULTI : 0; + + /* Unref the old BPF program (which will implicitly detach it) right before attaching the new program, to + * minimize the time window when we don't account for IP traffic. */ +@@ -711,8 +710,7 @@ int bpf_firewall_install(Unit *u) { + u->ip_bpf_ingress_installed = bpf_program_unref(u->ip_bpf_ingress_installed); + + if (u->ip_bpf_egress) { +- r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, +- flags | (set_isempty(u->ip_bpf_custom_egress) ? 0 : BPF_F_ALLOW_MULTI)); ++ r = bpf_program_cgroup_attach(u->ip_bpf_egress, BPF_CGROUP_INET_EGRESS, path, flags); + if (r < 0) + return log_unit_error_errno(u, r, "Attaching egress BPF program to cgroup %s failed: %m", path); + +@@ -721,8 +719,7 @@ int bpf_firewall_install(Unit *u) { + } + + if (u->ip_bpf_ingress) { +- r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, +- flags | (set_isempty(u->ip_bpf_custom_ingress) ? 0 : BPF_F_ALLOW_MULTI)); ++ r = bpf_program_cgroup_attach(u->ip_bpf_ingress, BPF_CGROUP_INET_INGRESS, path, flags); + if (r < 0) + return log_unit_error_errno(u, r, "Attaching ingress BPF program to cgroup %s failed: %m", path); + +diff --git a/src/core/main.c b/src/core/main.c +index a280b756ff..2ace4cb89c 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -1144,6 +1144,14 @@ static int prepare_reexecute( + if (!fds) + return log_oom(); + ++ /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF ++ * program is active during task execution within a cgroup. This would be bad since this may have ++ * security or reliability implications: devices we should filter won't be filtered, network activity ++ * we should filter won't be filtered, etc. We pin all the existing devices by bumping their ++ * refcount, and then storing them to later have it decremented. */ ++ _cleanup_(manager_unpin_all_cgroup_bpf_programsp) Manager *m_unpin = ++ manager_pin_all_cgroup_bpf_programs(m); ++ + r = manager_serialize(m, f, fds, switching_root); + if (r < 0) + return r; +@@ -1159,6 +1167,7 @@ static int prepare_reexecute( + if (r < 0) + return log_error_errno(r, "Failed to disable O_CLOEXEC for serialization fds: %m"); + ++ TAKE_PTR(m_unpin); + *ret_f = TAKE_PTR(f); + *ret_fds = TAKE_PTR(fds); + +diff --git a/src/core/manager.c b/src/core/manager.c +index a1d6f7cc10..b373d27844 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -65,6 +65,7 @@ + #include "rm-rf.h" + #include "selinux-util.h" + #include "serialize.h" ++#include "set.h" + #include "signal-util.h" + #include "socket-util.h" + #include "special.h" +@@ -3217,6 +3218,79 @@ static void manager_serialize_gid_refs(Manager *m, FILE *f) { + manager_serialize_uid_refs_internal(m, f, &m->gid_refs, "destroy-ipc-gid"); + } + ++static int serialize_limbo_bpf_program(FILE *f, FDSet *fds, BPFProgram *p) { ++ int copy; ++ _cleanup_free_ char *ap = NULL; ++ ++ /* We don't actually need the instructions or other data, since this is only used on the other side ++ * for BPF limbo, which just requires the program type, cgroup path, and kernel-facing BPF file ++ * descriptor. We don't even need to know what unit or directive it's attached to, since we're just ++ * going to expire it after coldplug. */ ++ ++ assert(f); ++ assert(p); ++ ++ /* If the program isn't attached to the kernel yet, there's no reason to serialise it for limbo. Just ++ * let it be skeletonized and then coldplug can do the work on the other side if it's still ++ * necessary. */ ++ if (p->kernel_fd < 0 || !p->attached_path) ++ return -ENOTCONN; ++ ++ copy = fdset_put_dup(fds, p->kernel_fd); ++ if (copy < 0) ++ return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m"); ++ ++ /* Otherwise, on daemon-reload, we'd remain pinned. */ ++ safe_close(p->kernel_fd); ++ ++ ap = cescape(p->attached_path); ++ if (!ap) ++ return log_oom(); ++ ++ return serialize_item_format(f, "bpf-limbo", "%i %i %i \"%s\"", ++ copy, p->prog_type, p->attached_type, ap); ++} ++ ++static void deserialize_limbo_bpf_program(Manager *m, FDSet *fds, const char *value) { ++ _cleanup_free_ char *raw_fd = NULL, *raw_pt = NULL, *raw_at = NULL, *cgpath = NULL; ++ int fd, r, prog_type, attached_type; ++ ++ assert(m); ++ assert(value); ++ ++ r = extract_first_word(&value, &raw_fd, NULL, 0); ++ if (r <= 0 || safe_atoi(raw_fd, &fd) < 0 || fd < 0 || !fdset_contains(fds, fd)) ++ return (void) log_error("Failed to parse bpf-limbo FD: %s", value); ++ ++ r = extract_first_word(&value, &raw_pt, NULL, 0); ++ if (r <= 0 || safe_atoi(raw_pt, &prog_type) < 0) ++ return (void) log_error("Failed to parse bpf-limbo program type: %s", value); ++ ++ r = extract_first_word(&value, &raw_at, NULL, 0); ++ if (r <= 0 || safe_atoi(raw_at, &attached_type) < 0) ++ return (void) log_error("Failed to parse bpf-limbo attached type: %s", value); ++ ++ r = extract_first_word(&value, &cgpath, NULL, EXTRACT_CUNESCAPE | EXTRACT_UNQUOTE); ++ if (r <= 0) ++ return (void) log_error("Failed to parse attached path for BPF limbo FD %s", value); ++ ++ _cleanup_(bpf_program_unrefp) BPFProgram *p = NULL; ++ r = bpf_program_new(prog_type, &p); ++ if (r < 0) ++ return (void) log_error_errno(r, "Failed to create BPF limbo program: %m"); ++ ++ /* Just enough to free it when the time is right, this does not have enough information be used as a ++ * real BPFProgram. */ ++ p->attached_type = attached_type; ++ p->kernel_fd = fdset_remove(fds, fd); ++ p->attached_path = TAKE_PTR(cgpath); ++ ++ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); ++ if (r < 0) ++ return (void) log_error_errno(r, "Failed to register BPF limbo program for FD %s: %m", value); ++ TAKE_PTR(p); ++} ++ + int manager_serialize( + Manager *m, + FILE *f, +@@ -3226,6 +3300,7 @@ int manager_serialize( + const char *t; + Unit *u; + int r; ++ BPFProgram *p; + + assert(m); + assert(f); +@@ -3270,6 +3345,9 @@ int manager_serialize( + (void) serialize_dual_timestamp(f, joined, m->timestamps + q); + } + ++ SET_FOREACH(p, m->bpf_limbo_progs) ++ (void) serialize_limbo_bpf_program(f, fds, p); ++ + if (!switching_root) + (void) serialize_strv(f, "env", m->client_environment); + +@@ -3588,7 +3666,10 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + else + m->n_failed_jobs += n; + +- } else if ((val = startswith(l, "taint-usr="))) { ++ } else if ((val = startswith(l, "bpf-limbo="))) ++ deserialize_limbo_bpf_program(m, fds, val); ++ ++ else if ((val = startswith(l, "taint-usr="))) { + int b; + + b = parse_boolean(val); +@@ -3764,6 +3845,65 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) { + return manager_deserialize_units(m, f, fds); + } + ++Manager* manager_pin_all_cgroup_bpf_programs(Manager *m) { ++ int r; ++ Unit *u; ++ ++ assert(m); ++ ++ HASHMAP_FOREACH(u, m->units) { ++ BPFProgram *p; ++ ++ FOREACH_POINTER(p, ++ u->bpf_device_control_installed, ++ u->ip_bpf_ingress, ++ u->ip_bpf_ingress_installed, ++ u->ip_bpf_egress, ++ u->ip_bpf_egress_installed) ++ if (p) { ++ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); ++ if (r < 0) { ++ log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m"); ++ continue; ++ } ++ ++ bpf_program_ref(p); ++ } ++ ++ Set *s; ++ FOREACH_POINTER(s, ++ u->ip_bpf_custom_ingress, ++ u->ip_bpf_custom_ingress_installed, ++ u->ip_bpf_custom_egress, ++ u->ip_bpf_custom_egress_installed) ++ SET_FOREACH(p, s) { ++ r = set_ensure_put(&m->bpf_limbo_progs, NULL, p); ++ if (r < 0) { ++ log_unit_error_errno(u, r, "Cannot store BPF program for reload, ignoring: %m"); ++ continue; ++ } ++ ++ bpf_program_ref(p); ++ } ++ } ++ ++ log_debug("Pinned %d BPF programs", set_size(m->bpf_limbo_progs)); ++ ++ return m; ++} ++ ++static void manager_skeletonize_all_cgroup_bpf_programs(Manager *m) { ++ BPFProgram *p; ++ ++ SET_FOREACH(p, m->bpf_limbo_progs) ++ bpf_program_skeletonize(p); ++} ++ ++void manager_unpin_all_cgroup_bpf_programs(Manager *m) { ++ log_debug("Unpinning %d BPF programs", set_size(m->bpf_limbo_progs)); ++ set_clear_with_destructor(m->bpf_limbo_progs, bpf_program_unref); ++} ++ + int manager_reload(Manager *m) { + _cleanup_(manager_reloading_stopp) Manager *reloading = NULL; + _cleanup_fdset_free_ FDSet *fds = NULL; +@@ -3783,6 +3923,13 @@ int manager_reload(Manager *m) { + /* We are officially in reload mode from here on. */ + reloading = manager_reloading_start(m); + ++ /* We need existing BPF programs to survive reload, otherwise there will be a period where no BPF ++ * program is active during task execution within a cgroup. This would be bad since this may have ++ * security or reliability implications: devices we should filter won't be filtered, network activity ++ * we should filter won't be filtered, etc. We pin all the existing devices by bumping their ++ * refcount, and then storing them to later have it decremented. */ ++ (void) manager_pin_all_cgroup_bpf_programs(m); ++ + r = manager_serialize(m, f, fds, false); + if (r < 0) + return r; +@@ -3807,6 +3954,12 @@ int manager_reload(Manager *m) { + m->uid_refs = hashmap_free(m->uid_refs); + m->gid_refs = hashmap_free(m->gid_refs); + ++ /* The only canonical reference left to the dynamically allocated parts of these BPF programs is ++ * going to be on the other side of manager_deserialize, so the freeable parts can now be freed. The ++ * program itself will be detached as part of manager_vacuum. */ ++ manager_skeletonize_all_cgroup_bpf_programs(m); ++ m->bpf_limbo_progs = set_free(m->bpf_limbo_progs); ++ + r = lookup_paths_init(&m->lookup_paths, m->unit_file_scope, 0, NULL); + if (r < 0) + log_warning_errno(r, "Failed to initialize path lookup table, ignoring: %m"); +@@ -4741,6 +4894,12 @@ static void manager_vacuum(Manager *m) { + + /* Release any runtimes no longer referenced */ + exec_runtime_vacuum(m); ++ ++ /* Release any outmoded BPF programs that were deserialized from the previous manager, since new ones ++ * should be in action now. We first need to make sure all entries in the cgroup realize queue are ++ * complete, otherwise BPF firewalls/etc may not have been set up yet. */ ++ (void) manager_dispatch_cgroup_realize_queue(m); ++ manager_unpin_all_cgroup_bpf_programs(m); + } + + int manager_dispatch_user_lookup_fd(sd_event_source *source, int fd, uint32_t revents, void *userdata) { +diff --git a/src/core/manager.h b/src/core/manager.h +index 19df889dd8..2c4a2b6063 100644 +--- a/src/core/manager.h ++++ b/src/core/manager.h +@@ -438,6 +438,8 @@ struct Manager { + VarlinkServer *varlink_server; + /* Only systemd-oomd should be using this to subscribe to changes in ManagedOOM settings */ + Varlink *managed_oom_varlink_request; ++ ++ Set *bpf_limbo_progs; + }; + + static inline usec_t manager_default_timeout_abort_usec(Manager *m) { +@@ -479,6 +481,10 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode + int manager_add_job_by_name_and_warn(Manager *m, JobType type, const char *name, JobMode mode, Set *affected_jobs, Job **ret); + int manager_propagate_reload(Manager *m, Unit *unit, JobMode mode, sd_bus_error *e); + ++Manager* manager_pin_all_cgroup_bpf_programs(Manager *m); ++void manager_unpin_all_cgroup_bpf_programs(Manager *m); ++DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_unpin_all_cgroup_bpf_programs); ++ + void manager_dump_units(Manager *s, FILE *f, const char *prefix); + void manager_dump_jobs(Manager *s, FILE *f, const char *prefix); + void manager_dump(Manager *s, FILE *f, const char *prefix); +diff --git a/src/shared/bpf-program.c b/src/shared/bpf-program.c +index 10239142af..549490da6c 100644 +--- a/src/shared/bpf-program.c ++++ b/src/shared/bpf-program.c +@@ -209,6 +209,16 @@ int bpf_program_cgroup_detach(BPFProgram *p) { + return 0; + } + ++void bpf_program_skeletonize(BPFProgram *p) { ++ assert(p); ++ ++ /* Called shortly after serialization. From this point on, we are frozen for serialization and entry ++ * into BPF limbo, so we should proactively free our instructions and attached path. However, we ++ * shouldn't detach the program or close the kernel FD -- we need those on the other side. */ ++ free(p->instructions); ++ free(p->attached_path); ++} ++ + int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) { + union bpf_attr attr; + int fd; +diff --git a/src/shared/bpf-program.h b/src/shared/bpf-program.h +index eef77f9d8e..5957a6ce30 100644 +--- a/src/shared/bpf-program.h ++++ b/src/shared/bpf-program.h +@@ -28,6 +28,7 @@ struct BPFProgram { + int bpf_program_new(uint32_t prog_type, BPFProgram **ret); + BPFProgram *bpf_program_unref(BPFProgram *p); + BPFProgram *bpf_program_ref(BPFProgram *p); ++void bpf_program_skeletonize(BPFProgram *p); + + int bpf_program_add_instructions(BPFProgram *p, const struct bpf_insn *insn, size_t count); + int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size); +-- +2.29.2 + diff --git a/SOURCES/17872.patch b/SOURCES/17872.patch new file mode 100644 index 0000000..ffedc20 --- /dev/null +++ b/SOURCES/17872.patch @@ -0,0 +1,102 @@ +From 963a018bade094e38a71bf1b7e10d37b44225836 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Sun, 6 Dec 2020 22:29:43 +0900 +Subject: [PATCH 2/3] core/namespace: use existing /proc when not enough + priviledge + +Fixes #17860. +--- + src/core/namespace.c | 61 ++++++++++++++++++++++++-------------------- + 1 file changed, 34 insertions(+), 27 deletions(-) + +diff --git a/src/core/namespace.c b/src/core/namespace.c +index cdf427a6ea..8560ad9a75 100644 +--- a/src/core/namespace.c ++++ b/src/core/namespace.c +@@ -859,25 +859,15 @@ static int mount_sysfs(const MountEntry *m) { + } + + static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { ++ _cleanup_free_ char *opts = NULL; + const char *entry_path; +- int r; ++ int r, n; + + assert(m); + assert(ns_info); + +- entry_path = mount_entry_path(m); +- +- /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in +- * one. i.e we don't reuse existing mounts here under any condition, we want a new instance owned by +- * our user namespace and with our hidepid= settings applied. Hence, let's get rid of everything +- * mounted on /proc/ first. */ +- +- (void) mkdir_p_label(entry_path, 0755); +- (void) umount_recursive(entry_path, 0); +- + if (ns_info->protect_proc != PROTECT_PROC_DEFAULT || + ns_info->proc_subset != PROC_SUBSET_ALL) { +- _cleanup_free_ char *opts = NULL; + + /* Starting with kernel 5.8 procfs' hidepid= logic is truly per-instance (previously it + * pretended to be per-instance but actually was per-namespace), hence let's make use of it +@@ -891,23 +881,40 @@ static int mount_procfs(const MountEntry *m, const NamespaceInfo *ns_info) { + ns_info->proc_subset == PROC_SUBSET_PID ? ",subset=pid" : ""); + if (!opts) + return -ENOMEM; +- +- r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); +- if (r < 0) { +- if (r != -EINVAL) +- return r; +- +- /* If this failed with EINVAL then this likely means the textual hidepid= stuff is +- * not supported by the kernel, and thus the per-instance hidepid= neither, which +- * means we really don't want to use it, since it would affect our host's /proc +- * mount. Hence let's gracefully fallback to a classic, unrestricted version. */ +- } else +- return 1; + } + +- r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); +- if (r < 0) +- return r; ++ entry_path = mount_entry_path(m); ++ (void) mkdir_p_label(entry_path, 0755); ++ ++ /* Mount a new instance, so that we get the one that matches our user namespace, if we are running in ++ * one. i.e we don't reuse existing mounts here under any condition, we want a new instance owned by ++ * our user namespace and with our hidepid= settings applied. Hence, let's get rid of everything ++ * mounted on /proc/ first. */ ++ ++ n = umount_recursive(entry_path, 0); ++ ++ r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, opts); ++ if (r == -EINVAL && opts) ++ /* If this failed with EINVAL then this likely means the textual hidepid= stuff is ++ * not supported by the kernel, and thus the per-instance hidepid= neither, which ++ * means we really don't want to use it, since it would affect our host's /proc ++ * mount. Hence let's gracefully fallback to a classic, unrestricted version. */ ++ r = mount_nofollow_verbose(LOG_DEBUG, "proc", entry_path, "proc", MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL); ++ if (r == -EPERM) { ++ /* When we do not have enough priviledge to mount /proc, fallback to use existing /proc. */ ++ ++ if (n > 0) ++ /* /proc or some of sub-mounts are umounted in the above. Refuse incomplete tree. ++ * Propagate the original error code returned by mount() in the above. */ ++ return -EPERM; ++ ++ r = path_is_mount_point(entry_path, NULL, 0); ++ if (r < 0) ++ return log_debug_errno(r, "Unable to determine whether /proc is already mounted: %m"); ++ if (r == 0) ++ /* /proc is not mounted. Propagate the original error code. */ ++ return -EPERM; ++ } + + return 1; + } +-- +2.29.2 + diff --git a/SOURCES/18211.patch b/SOURCES/18211.patch new file mode 100644 index 0000000..15a2d9b --- /dev/null +++ b/SOURCES/18211.patch @@ -0,0 +1,109 @@ +From 51f14e78a2ae0a971af1ce3cfcbbf8ca8250ca22 Mon Sep 17 00:00:00 2001 +From: Anita Zhang +Date: Mon, 11 Jan 2021 20:04:20 -0800 +Subject: [PATCH 1/3] core: update setings on the unit and job as the result of + ExecCondition= + +Update ExecCondition= to set Unit->condition_result and return JOB_DONE +in the Job results if the check fails so as to match the current behavior +of ConditionXYZ= w.r.t units/jobs dependency checks. + +Fixes: #18207 +--- + src/core/job.c | 3 +-- + src/core/service.c | 17 ++++++++++------- + src/core/unit.c | 2 -- + src/core/unit.h | 1 - + 4 files changed, 11 insertions(+), 12 deletions(-) + +diff --git a/src/core/job.c b/src/core/job.c +index f3c1a02831..7d5c288ea4 100644 +--- a/src/core/job.c ++++ b/src/core/job.c +@@ -882,8 +882,7 @@ static void job_log_done_status_message(Unit *u, uint32_t job_id, JobType t, Job + return; + + /* Show condition check message if the job did not actually do anything due to failed condition. */ +- if ((t == JOB_START && result == JOB_DONE && !u->condition_result) || +- (t == JOB_START && result == JOB_SKIPPED)) { ++ if (t == JOB_START && result == JOB_DONE && !u->condition_result) { + log_struct(LOG_INFO, + "MESSAGE=Condition check resulted in %s being skipped.", unit_status_string(u), + "JOB_ID=%" PRIu32, job_id, +diff --git a/src/core/service.c b/src/core/service.c +index d7bdeb7cca..3b144153f4 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -1129,8 +1129,7 @@ static void service_set_state(Service *s, ServiceState state) { + + unit_notify(UNIT(s), table[old_state], table[state], + (s->reload_result == SERVICE_SUCCESS ? 0 : UNIT_NOTIFY_RELOAD_FAILURE) | +- (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0) | +- (s->result == SERVICE_SKIP_CONDITION ? UNIT_NOTIFY_SKIP_CONDITION : 0)); ++ (s->will_auto_restart ? UNIT_NOTIFY_WILL_AUTO_RESTART : 0)); + } + + static usec_t service_coldplug_timeout(Service *s) { +@@ -3546,10 +3545,6 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + } else if (s->control_pid == pid) { + s->control_pid = 0; + +- /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */ +- if (f == SERVICE_FAILURE_EXIT_CODE && s->state == SERVICE_CONDITION && status < 255) +- f = SERVICE_SKIP_CONDITION; +- + if (s->control_command) { + exec_status_exit(&s->control_command->exec_status, &s->exec_context, pid, code, status); + +@@ -3557,6 +3552,15 @@ static void service_sigchld_event(Unit *u, pid_t pid, int code, int status) { + f = SERVICE_SUCCESS; + } + ++ /* ExecCondition= calls that exit with (0, 254] should invoke skip-like behavior instead of failing */ ++ if (s->state == SERVICE_CONDITION) { ++ if (f == SERVICE_FAILURE_EXIT_CODE && status < 255) { ++ UNIT(s)->condition_result = false; ++ f = SERVICE_SKIP_CONDITION; ++ } else if (f == SERVICE_SUCCESS) ++ UNIT(s)->condition_result = true; ++ } ++ + unit_log_process_exit( + u, + "Control process", +@@ -4601,7 +4605,6 @@ const UnitVTable service_vtable = { + }, + .finished_start_job = { + [JOB_FAILED] = "Failed to start %s.", +- [JOB_SKIPPED] = "Skipped %s.", + }, + .finished_stop_job = { + [JOB_DONE] = "Stopped %s.", +diff --git a/src/core/unit.c b/src/core/unit.c +index 45a417a090..9614fb84aa 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -2561,8 +2561,6 @@ static bool unit_process_job(Job *j, UnitActiveState ns, UnitNotifyFlags flags) + if (UNIT_IS_INACTIVE_OR_FAILED(ns)) { + if (ns == UNIT_FAILED) + result = JOB_FAILED; +- else if (FLAGS_SET(flags, UNIT_NOTIFY_SKIP_CONDITION)) +- result = JOB_SKIPPED; + else + result = JOB_DONE; + +diff --git a/src/core/unit.h b/src/core/unit.h +index 02b2b24206..f040e9dfe6 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -738,7 +738,6 @@ int unit_kill_common(Unit *u, KillWho who, int signo, pid_t main_pid, pid_t cont + typedef enum UnitNotifyFlags { + UNIT_NOTIFY_RELOAD_FAILURE = 1 << 0, + UNIT_NOTIFY_WILL_AUTO_RESTART = 1 << 1, +- UNIT_NOTIFY_SKIP_CONDITION = 1 << 2, + } UnitNotifyFlags; + + void unit_notify(Unit *u, UnitActiveState os, UnitActiveState ns, UnitNotifyFlags flags); +-- +2.29.2 + diff --git a/SOURCES/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch b/SOURCES/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch new file mode 100644 index 0000000..84497ad --- /dev/null +++ b/SOURCES/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch @@ -0,0 +1,129 @@ +From f58b96d3e8d1cb0dd3666bc74fa673918b586612 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Mon, 14 Sep 2020 17:58:03 +0200 +Subject: [PATCH] test-mountpointutil-util: do not assert in test_mnt_id() + +https://bugzilla.redhat.com/show_bug.cgi?id=1803070 + +I *think* this a kernel bug: the mnt_id as listed in /proc/self/mountinfo is different +than the one we get from /proc/self/fdinfo/. This only matters when both statx and +name_to_handle_at are unavailable and we hit the fallback path that goes through fdinfo: + +(gdb) !uname -r +5.6.19-200.fc31.ppc64le + +(gdb) !cat /proc/self/mountinfo +697 664 253:0 /var/lib/mock/fedora-31-ppc64le/root / rw,relatime shared:298 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota +698 697 253:0 /var/cache/mock/fedora-31-ppc64le/yum_cache /var/cache/yum rw,relatime shared:299 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota +699 697 253:0 /var/cache/mock/fedora-31-ppc64le/dnf_cache /var/cache/dnf rw,relatime shared:300 master:1 - xfs /dev/mapper/fedora_rh--power--vm14-root rw,seclabel,attr2,inode64,logbufs=8,logbsize=32k,noquota +700 697 0:32 /mock-selinux-plugin.7me9bfpi /proc/filesystems rw,nosuid,nodev shared:301 master:18 - tmpfs tmpfs rw,seclabel <========================================================== +701 697 0:41 / /sys ro,nosuid,nodev,noexec,relatime shared:302 - sysfs sysfs ro,seclabel +702 701 0:21 / /sys/fs/selinux ro,nosuid,nodev,noexec,relatime shared:306 master:8 - selinuxfs selinuxfs rw +703 697 0:42 / /dev rw,nosuid shared:303 - tmpfs tmpfs rw,seclabel,mode=755 +704 703 0:43 / /dev/shm rw,nosuid,nodev shared:304 - tmpfs tmpfs rw,seclabel +705 703 0:45 / /dev/pts rw,nosuid,noexec,relatime shared:307 - devpts devpts rw,seclabel,gid=5,mode=620,ptmxmode=666 +706 703 0:6 /btrfs-control /dev/btrfs-control rw,nosuid shared:308 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +707 703 0:6 /loop-control /dev/loop-control rw,nosuid shared:309 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +708 703 0:6 /loop0 /dev/loop0 rw,nosuid shared:310 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +709 703 0:6 /loop1 /dev/loop1 rw,nosuid shared:311 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +710 703 0:6 /loop10 /dev/loop10 rw,nosuid shared:312 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +711 703 0:6 /loop11 /dev/loop11 rw,nosuid shared:313 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +712 703 0:6 /loop2 /dev/loop2 rw,nosuid shared:314 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +713 703 0:6 /loop3 /dev/loop3 rw,nosuid shared:315 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +714 703 0:6 /loop4 /dev/loop4 rw,nosuid shared:316 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +715 703 0:6 /loop5 /dev/loop5 rw,nosuid shared:317 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +716 703 0:6 /loop6 /dev/loop6 rw,nosuid shared:318 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +717 703 0:6 /loop7 /dev/loop7 rw,nosuid shared:319 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +718 703 0:6 /loop8 /dev/loop8 rw,nosuid shared:320 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +719 703 0:6 /loop9 /dev/loop9 rw,nosuid shared:321 master:9 - devtmpfs devtmpfs rw,seclabel,size=4107840k,nr_inodes=64185,mode=755 +720 697 0:44 / /run rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +721 720 0:25 /systemd/nspawn/propagate/9cc8a155d0244558b273f773d2b92142 /run/systemd/nspawn/incoming ro master:12 - tmpfs tmpfs rw,seclabel,mode=755 +722 697 0:32 /mock-resolv.dvml91hp /etc/resolv.conf rw,nosuid,nodev shared:322 master:18 - tmpfs tmpfs rw,seclabel +725 697 0:47 / /proc rw,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +603 725 0:47 /sys /proc/sys ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +604 725 0:44 /systemd/inaccessible/reg /proc/kallsyms ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +605 725 0:44 /systemd/inaccessible/reg /proc/kcore ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +606 725 0:44 /systemd/inaccessible/reg /proc/keys ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +607 725 0:44 /systemd/inaccessible/reg /proc/sysrq-trigger ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +608 725 0:44 /systemd/inaccessible/reg /proc/timer_list ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +609 725 0:47 /bus /proc/bus ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +610 725 0:47 /fs /proc/fs ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +611 725 0:47 /irq /proc/irq ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +612 725 0:47 /scsi /proc/scsi ro,nosuid,nodev,noexec,relatime shared:323 - proc proc rw +613 703 0:46 / /dev/mqueue rw,nosuid,nodev,noexec,relatime shared:324 - mqueue mqueue rw,seclabel +614 701 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime shared:325 - cgroup2 cgroup rw,seclabel,nsdelegate +615 603 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id ro,nosuid,nodev,noexec shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +616 725 0:44 /.#proc-sys-kernel-random-boot-id4fbdce67af46d1c2//deleted /proc/sys/kernel/random/boot_id rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755 +617 725 0:44 /.#proc-kmsg5b7a8bcfe6717139//deleted /proc/kmsg rw,nosuid,nodev shared:305 - tmpfs tmpfs rw,seclabel,mode=755 + +The test process does +name_to_handle_at("/proc/filesystems") which returns -EOPNOTSUPP, and then +openat(AT_FDCWD, "/proc/filesystems") which returns 4, and then +read(open("/proc/self/fdinfo/4", ...)) which gives +"pos:\t0\nflags:\t012100000\nmnt_id:\t725\n" + +and the "725" is clearly inconsistent with "700" in /proc/self/mountinfo. + +We could either drop the fallback path (and fail name_to_handle_at() is not +avaliable) or ignore the error in the test. Not sure what is better. I think +this issue only occurs sometimes and with older kernels, so probably continuing +with the current flaky implementation is better than ripping out the fallback. + +Another strace: +writev(2, [{iov_base="mnt ids of /proc/sys is 603", iov_len=27}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/sys is 603 +) = 28 +name_to_handle_at(AT_FDCWD, "/", {handle_bytes=128 => 12, handle_type=129, f_handle=0x52748401000000008b93e20d}, [697], 0) = 0 +writev(2, [{iov_base="mnt ids of / is 697", iov_len=19}, {iov_base="\n", iov_len=1}], 2mnt ids of / is 697 +) = 20 +name_to_handle_at(AT_FDCWD, "/proc/kcore", {handle_bytes=128 => 12, handle_type=1, f_handle=0x92ddcfcd2e802d0100000000}, [605], 0) = 0 +writev(2, [{iov_base="mnt ids of /proc/kcore is 605", iov_len=29}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/kcore is 605 +) = 30 +name_to_handle_at(AT_FDCWD, "/dev", {handle_bytes=128 => 12, handle_type=1, f_handle=0x8ae269160c802d0100000000}, [703], 0) = 0 +writev(2, [{iov_base="mnt ids of /dev is 703", iov_len=22}, {iov_base="\n", iov_len=1}], 2mnt ids of /dev is 703 +) = 23 +name_to_handle_at(AT_FDCWD, "/proc/filesystems", {handle_bytes=128}, 0x7fffe36ddb84, 0) = -1 EOPNOTSUPP (Operation not supported) +openat(AT_FDCWD, "/proc/filesystems", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_PATH) = 4 +openat(AT_FDCWD, "/proc/self/fdinfo/4", O_RDONLY|O_CLOEXEC) = 5 +fstat(5, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0 +fstat(5, {st_mode=S_IFREG|0400, st_size=0, ...}) = 0 +read(5, "pos:\t0\nflags:\t012100000\nmnt_id:\t725\n", 2048) = 36 +read(5, "", 1024) = 0 +close(5) = 0 +close(4) = 0 +writev(2, [{iov_base="mnt ids of /proc/filesystems are 700, 725", iov_len=41}, {iov_base="\n", iov_len=1}], 2mnt ids of /proc/filesystems are 700, 725 +) = 42 +writev(2, [{iov_base="the other path for mnt id 725 is /proc", iov_len=38}, {iov_base="\n", iov_len=1}], 2the other path for mnt id 725 is /proc +) = 39 +writev(2, [{iov_base="Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting.", iov_len=108}, {iov_base="\n", iov_len=1}], 2Assertion 'path_equal(p, t)' failed at src/test/test-mountpoint-util.c:94, function test_mnt_id(). Aborting. +) = 109 +rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0 +rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0 +getpid() = 20 +gettid() = 20 +tgkill(20, 20, SIGABRT) = 0 +rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0 +--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=20, si_uid=0} --- ++++ killed by SIGABRT (core dumped) +++ +--- + src/test/test-mountpoint-util.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/src/test/test-mountpoint-util.c b/src/test/test-mountpoint-util.c +index 30b00ae4d8b..ffe5144b04a 100644 +--- a/src/test/test-mountpoint-util.c ++++ b/src/test/test-mountpoint-util.c +@@ -89,8 +89,12 @@ static void test_mnt_id(void) { + /* The ids don't match? If so, then there are two mounts on the same path, let's check if + * that's really the case */ + char *t = hashmap_get(h, INT_TO_PTR(mnt_id2)); +- log_debug("the other path for mnt id %i is %s\n", mnt_id2, t); +- assert_se(path_equal(p, t)); ++ log_debug("Path for mnt id %i from /proc/self/mountinfo is %s\n", mnt_id2, t); ++ ++ if (!path_equal(p, t)) ++ /* Apparent kernel bug in /proc/self/fdinfo */ ++ log_warning("Bad mount id given for %s: %d, should be %d", ++ p, mnt_id2, mnt_id); + } + } + diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 578eccc..f6df179 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -1,15 +1,4 @@ -# Meson settings -%global _vpath_srcdir . -%global _vpath_builddir %{_target_platform} -%global __global_cflags %{optflags} -%global __global_cxxflags %{optflags} -%global __global_fflags %{optflags} -I%_fmoddir -%global __global_fcflags %{optflags} -I%_fmoddir -%global __global_ldflags -Wl,-z,relro %{_hardened_ldflags} - -%define _python_bytecompile_errors_terminate_build 0 - -#global commit 7f56c26d1041e686efa72b339250a98fb6ee8f00 +#global commit 551dd873b0bdfb9e7e47431b2933c8b910228f0c %{?commit:%global shortcommit %(c=%{commit}; echo ${c:0:7})} %global stable 1 @@ -27,11 +16,12 @@ # cryptsetup, e.g. when re-building cryptsetup on a json-c SONAME-bump. %bcond_with bootstrap %bcond_without tests +%bcond_without lto Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd -Version: 246.1 -Release: 2%{?dist} +Version: 247.3 +Release: 1%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -73,22 +63,19 @@ i=1; for j in 00*patch; do printf "Patch%04d: %s\n" $i $j; i=$((i+1));done| GIT_DIR=../../src/systemd/.git git diffab -M v233..master@{2017-06-15} -- hwdb/[67]* hwdb/parse_hwdb.py > hwdb.patch %endif -Patch0002: 0001-Revert-test-path-increase-timeout.patch -Patch0003: 0002-test-path-do-not-fail-the-test-if-we-fail-to-start-s.patch - -Patch0004: 0001-test-acl-util-output-more-debug-info.patch -Patch0005: 0001-Do-not-assert-in-test_add_acls_for_user.patch - -Patch1002: 16838_16857_improve_path_search.patch -Patch1003: 16940_cleanup_socket_econn_handling.patch -Patch1004: 17031_propagate_start_limit_hit.patch -Patch1005: 17082_nspawn_tty_tweaks.patch - -Patch1006: 0001-bpf-pid1-Pin-reference-to-BPF-programs-for-post-cold.patch -Patch1007: 0002-core-clean-up-inactive-failed-service-scope-s-cgroup.patch -Patch1008: 0003-timer-add-new-feature-FixedRandomDelay.patch +# Backports of patches from upstream (0000–0499) +# 18211: Fixes ExecCondition= dependency bug +Patch0000: https://github.com/systemd/systemd/pull/18211.patch +# 17872: Fixes using PrivateUsers=yes with other sandboxing properties +Patch0001: https://github.com/systemd/systemd/pull/17872.patch +%if 0%{?facebook} +# 17495: Fixes BPF pinning post-coldplug +Patch0002: https://github.com/systemd/systemd/pull/17495.patch +%endif -Patch1009: 16803_fix_asserts_conditions.patch +# Downstream-only patches (0500–9999) +# https://github.com/systemd/systemd/pull/17050 +Patch0501: https://github.com/systemd/systemd/pull/17050/commits/f58b96d3e8d1cb0dd3666bc74fa673918b586612.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -140,8 +127,6 @@ BuildRequires: tree BuildRequires: hostname BuildRequires: python3-devel BuildRequires: python3-lxml -BuildRequires: python3 -%global __python3 /usr/bin/python3 %if 0%{?have_gnu_efi} BuildRequires: gnu-efi gnu-efi-devel %endif @@ -151,6 +136,8 @@ BuildRequires: gettext # We use RUNNING_ON_VALGRIND in tests, so the headers need to be available BuildRequires: valgrind-devel BuildRequires: pkgconfig(bash-completion) +BuildRequires: perl +BuildRequires: perl(IPC::SysV) Requires(post): coreutils Requires(post): sed @@ -176,14 +163,31 @@ Obsoletes: system-setup-keyboard < 0.9 Provides: system-setup-keyboard = 0.9 # systemd-sysv-convert was removed in f20: https://fedorahosted.org/fpc/ticket/308 Obsoletes: systemd-sysv < 206 +%if 0%{?facebook} == 0 # self-obsoletes so that dnf will install new subpackages on upgrade (#1260394) -Obsoletes: %{name} < 229-5 +Obsoletes: %{name} < 246.6-2 +Conflicts: initscripts < 9.56.1 +%endif Provides: systemd-sysv = 206 %if 0%{?fedora} Conflicts: fedora-release < 23-0.12 %endif Obsoletes: timedatex < 0.6-3 Provides: timedatex = 0.6-3 +Conflicts: %{name}-standalone-tmpfiles < %{version}-%{release}^ +Obsoletes: %{name}-standalone-tmpfiles < %{version}-%{release}^ +Conflicts: %{name}-standalone-sysusers < %{version}-%{release}^ +Obsoletes: %{name}-standalone-sysusers < %{version}-%{release}^ + +# Recommends to replace normal Requires deps for stuff that is dlopen()ed +Recommends: libcryptsetup.so.12()(64bit) +Recommends: libcryptsetup.so.12(CRYPTSETUP_2.0)(64bit) +Recommends: libidn2.so.0()(64bit) +Recommends: libidn2.so.0(IDN2_0.0.0)(64bit) +Recommends: libpcre2-8.so.0()(64bit) +Recommends: libpwquality.so.1()(64bit) +Recommends: libpwquality.so.1(LIBPWQUALITY_1.0)(64bit) +Recommends: libqrencode.so.4()(64bit) %description systemd is a system and service manager that runs as PID 1 and starts @@ -263,16 +267,14 @@ Requires(preun): systemd Requires(postun): systemd Requires(post): grep Requires: kmod >= 18-4 -%if 0%{?facebook} -# obsolete parent package so that dnf will install new subpackage on upgrade (#1260394) -Obsoletes: %{name} < 229-5 -%else +%if 0%{?facebook} == 0 # https://bodhi.fedoraproject.org/updates/FEDORA-2020-dd43dd05b1 Obsoletes: systemd < 245.6-1 %endif Provides: udev = %{version} Provides: udev%{_isa} = %{version} Obsoletes: udev < 183 + # https://bugzilla.redhat.com/show_bug.cgi?id=1377733#c9 Suggests: systemd-bootchart # https://bugzilla.redhat.com/show_bug.cgi?id=1408878 @@ -282,6 +284,10 @@ Requires: kbd Provides: u2f-hidraw-policy = 1.0.2-40 Obsoletes: u2f-hidraw-policy < 1.0.2-40 +# Recommends to replace normal Requires deps for stuff that is dlopen()ed +Recommends: libcryptsetup.so.12()(64bit) +Recommends: libcryptsetup.so.12(CRYPTSETUP_2.0)(64bit) + %description udev This package contains systemd-udev and the rules and hardware database needed to manage device nodes. This package is necessary on physical @@ -341,16 +347,17 @@ They can be useful to test systemd internals. %{!?ntpvendor: echo 'NTP vendor zone is not set!'; exit 1} CONFIGURE_OPTS=( + -Dmode=release -Dsysvinit-path=/etc/rc.d/init.d -Drc-local=/etc/rc.d/rc.local -Dntp-servers='0.%{ntpvendor}.pool.ntp.org 1.%{ntpvendor}.pool.ntp.org 2.%{ntpvendor}.pool.ntp.org 3.%{ntpvendor}.pool.ntp.org' + -Ddns-servers= -Duser-path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin -Dservice-watchdog= -Ddev-kvm-mode=0666 -Dkmod=true -Dxkbcommon=true -Dblkid=true - -Dfdisk=true -Dseccomp=true -Dima=true -Dselinux=true @@ -364,6 +371,7 @@ CONFIGURE_OPTS=( -Dpam=true -Dacl=true -Dsmack=true + -Dopenssl=true -Dgcrypt=true -Daudit=true -Delfutils=true @@ -373,8 +381,6 @@ CONFIGURE_OPTS=( -Dlibcryptsetup=false %endif -Delfutils=true - -Dpwquality=true - -Dqrencode=true -Dgnutls=true -Dmicrohttpd=true -Dlibidn2=true @@ -392,20 +398,38 @@ CONFIGURE_OPTS=( -Dusers-gid=100 -Dnobody-user=nobody -Dnobody-group=nobody + -Dcompat-mutable-uid-boundaries=true -Dsplit-usr=false -Dsplit-bin=true +%if %{with lto} -Db_lto=true +%else + -Db_lto=false +%endif -Db_ndebug=false -Dman=true -Dversion-tag=v%{version}-%{release} -Ddocdir=%{_pkgdocdir} - -Ddefault-hierarchy=legacy -) - -# FIXME: temporary hack to unbreak the build, as with audit link fails on -# test-emergency-action (https://pagure.io/centos-sig-hyperscale/sig/issue/13) -CONFIGURE_OPTS+=( - -Daudit=false + -Dfallback-hostname=fedora + -Ddefault-dnssec=no + # https://bugzilla.redhat.com/show_bug.cgi?id=1867830 + -Ddefault-mdns=no + -Ddefault-llmnr=resolve + # CentOS is missing newer deps required to include these + # But also these aren't as relevant for the hyperscale use case + -Dp11kit=false + -Duserdb=false + -Dhomed=false + -Drepart=false + -Dfdisk=false + -Dpwquality=false + -Dqrencode=false + -Dlibfido2=false + # Old version of PAM might not support files in /usr/lib/pam.d/ so + # stick with the old /etc/pam.d + -Dpamconfdir=/etc/pam.d + # Standalone binaries are only relevant on non-systemd systems + -Dstandalone-binaries=false ) %if 0%{?facebook} @@ -415,13 +439,13 @@ CONFIGURE_OPTS+=( -Dsupport-url='https://www.facebook.com/groups/prodos.users/' -Ddefault-hierarchy=unified -Dcontainer-uid-base-min=10485760 - -Dp11kit=false - -Duserdb=false - -Dhomed=false - -Drepart=false ) %endif +%if %{without lto} +%global _lto_cflags %nil +%endif + export LANG=en_US.UTF-8 export LC_ALL=en_US.UTF-8 %meson "${CONFIGURE_OPTS[@]}" @@ -528,7 +552,7 @@ install -m 0755 -D -t %{buildroot}%{_rpmconfigdir}/ %{SOURCE24} # Split files in build root into rpms. See split-files.py for the # rules towards the end, anything which is an exception needs a line # here. -%{__python3} %{SOURCE2} %buildroot </dev/null || : # Apply ACL to the journal directory setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ &>/dev/null || : +[ $1 -eq 1 ] || exit 0 + # We reset the enablement of all services upon initial installation # https://bugzilla.redhat.com/show_bug.cgi?id=1118740#c23 # This will fix up enablement of any preset services that got installed @@ -639,9 +665,26 @@ setfacl -Rnm g:wheel:rx,d:g:wheel:rx,g:adm:rx,d:g:adm:rx /var/log/journal/ &>/de # https://bugzilla.redhat.com/show_bug.cgi?id=1647172. # We also do this for user units, see # https://fedoraproject.org/wiki/Changes/Systemd_presets_for_user_units. -if [ $1 -eq 1 ] ; then - systemctl preset-all &>/dev/null || : - systemctl --global preset-all &>/dev/null || : +systemctl preset-all &>/dev/null || : +systemctl --global preset-all &>/dev/null || : + +# Create /etc/resolv.conf symlink. +# We would also create it using tmpfiles, but let's do this here +# too before NetworkManager gets a chance. (systemd-tmpfiles invocation above +# does not do this, because it's marked with ! and we don't specify --boot.) +# https://bugzilla.redhat.com/show_bug.cgi?id=1873856 +# +# If systemd is not running, don't overwrite the symlink because that +# will immediately break DNS resolution, since systemd-resolved is +# also not running (https://bugzilla.redhat.com/show_bug.cgi?id=1891847). +# +# Also don't creat the symlink to the stub when the stub is disabled (#1891847 again). +if test -d /run/systemd/system/ && + systemctl -q is-enabled systemd-resolved.service &>/dev/null && + ! mountpoint /etc/resolv.conf &>/dev/null && + ! systemd-analyze cat-config systemd/resolved.conf 2>/dev/null | \ + grep -qE '^DNSStubListener\s*=\s*([nN][oO]?|[fF]|[fF][aA][lL][sS][eE]|0|[oO][fF][fF])$'; then + ln -fsv ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf fi %preun @@ -663,10 +706,14 @@ fi # This is for upgrades from previous versions before systemd-resolved became the default. systemctl --no-reload preset systemd-resolved.service &>/dev/null || : -if systemctl is-enabled systemd-resolved.service &>/dev/null; then +if systemctl -q is-enabled systemd-resolved.service &>/dev/null; then + systemctl -q is-enabled NetworkManager.service 2>/dev/null && \ + ! test -L /etc/resolv.conf 2>/dev/null && \ + ! mountpoint /etc/resolv.conf &>/dev/null && \ grep -q 'Generated by NetworkManager' /etc/resolv.conf 2>/dev/null && \ echo -e '/etc/resolv.conf was generated by NetworkManager.\nRemoving it to let systemd-resolved manage this file.' && \ - mv -v /etc/resolv.conf /etc/resolv.conf.orig-with-nm || : + mv -v /etc/resolv.conf /etc/resolv.conf.orig-with-nm && \ + ln -sv ../run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 2>/dev/null || : systemctl start systemd-resolved.service &>/dev/null || : fi @@ -685,7 +732,7 @@ function mod_nss() { # Add nss-resolve to hosts grep -E -q '^hosts:.* resolve' "$1" || sed -i.bak -r -e ' - s/^(hosts):(.*) files( mdns4_minimal .NOTFOUND=return.)? dns myhostname/\1:\2 resolve [!UNAVAIL=return] myhostname files\3 dns/ + s/^(hosts):(.*) files( mdns4_minimal .NOTFOUND=return.)? dns myhostname/\1:\2 files\3 resolve [!UNAVAIL=return] myhostname dns/ ' "$1" &>/dev/null || : fi } @@ -739,8 +786,12 @@ if [ -f %{_localstatedir}/lib/systemd/clock ] ; then fi udevadm hwdb --update &>/dev/null + %systemd_post %udev_services -/usr/lib/systemd/systemd-random-seed save 2>&1 + +# Try to save the random seed, but don't complain if /dev/urandom is unavailable +/usr/lib/systemd/systemd-random-seed save 2>&1 | \ + grep -v 'Failed to open /dev/urandom' || : # Replace obsolete keymaps # https://bugzilla.redhat.com/show_bug.cgi?id=1151958 @@ -760,14 +811,11 @@ getent group systemd-journal-remote &>/dev/null || groupadd -r systemd-journal-r getent passwd systemd-journal-remote &>/dev/null || useradd -r -l -g systemd-journal-remote -d %{_localstatedir}/log/journal/remote -s /sbin/nologin -c "Journal Remote" systemd-journal-remote &>/dev/null || : %post journal-remote -%systemd_post systemd-journal-gatewayd.socket systemd-journal-gatewayd.service -%systemd_post systemd-journal-remote.socket systemd-journal-remote.service -%systemd_post systemd-journal-upload.service +%systemd_post systemd-journal-gatewayd.socket systemd-journal-gatewayd.service systemd-journal-remote.socket systemd-journal-remote.service systemd-journal-upload.service +%firewalld_reload %preun journal-remote -%systemd_preun systemd-journal-gatewayd.socket systemd-journal-gatewayd.service -%systemd_preun systemd-journal-remote.socket systemd-journal-remote.service -%systemd_preun systemd-journal-upload.service +%systemd_preun systemd-journal-gatewayd.socket systemd-journal-gatewayd.service systemd-journal-remote.socket systemd-journal-remote.service systemd-journal-upload.service if [ $1 -eq 1 ] ; then if [ -f %{_localstatedir}/lib/systemd/journal-upload/state -a ! -L %{_localstatedir}/lib/systemd/journal-upload ] ; then mkdir -p %{_localstatedir}/lib/private/systemd/journal-upload @@ -777,9 +825,7 @@ if [ $1 -eq 1 ] ; then fi %postun journal-remote -%systemd_postun_with_restart systemd-journal-gatewayd.service -%systemd_postun_with_restart systemd-journal-remote.service -%systemd_postun_with_restart systemd-journal-upload.service +%systemd_postun_with_restart systemd-journal-gatewayd.service systemd-journal-remote.service systemd-journal-upload.service %global _docdir_fmt %{name} @@ -822,6 +868,12 @@ fi %files tests -f .file-list-tests %changelog +* Wed Feb 17 2021 Anita Zhang - 247.3-1 +- New release for 247 +- Backport PR #18211 (Fixes ExecCondition= dependency bug) +- Backport PR #17872 (Fixes PrivateUsers=yes with other sandboxing properties) +- FB only backport PR #17495 (Fixes BPF pinning post-coldplug) + * Sun Feb 7 2021 Davide Cavalca - 246.1-2 - Initial Hyperscale SIG package - Update release to use %%dist macro @@ -830,8 +882,42 @@ fi - Drop no longer needed FB FusionIO patch - Temporarily disable audit support while debugging a link issue -* Mon Jan 25 2021 Anita Zhang - 246.1-1.fb6 -- Backport PR #16803 to fix ConditionEnvironment= +* Tue Feb 2 2021 Zbigniew Jędrzejewski-Szmek - 247.3-1 +- Minor stable release +- Fixes #1895937, #1813219, #1903106. + +* Wed Jan 27 2021 Fedora Release Engineering +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jan 13 2021 Zbigniew Jędrzejewski-Szmek - 247.2-2 +- Fix bfq patch again (#1813219) + +* Wed Dec 23 2020 Jonathan Underwood - 247.2-2 +- Add patch to enable crypttab to support disabling of luks read and + write workqueues (corresponding to + https://github.com/systemd/systemd/pull/18062/). + +* Wed Dec 16 2020 Zbigniew Jędrzejewski-Szmek - 247.2-1 +- Minor stable release +- Fixes #1908071. + +* Tue Dec 8 2020 Zbigniew Jędrzejewski-Szmek - 247.1-3 +- Rebuild with fallback hostname change reverted. + +* Fri Dec 4 2020 Bastien Nocera - 247.1-2 +- Unset fallback-hostname as plenty of applications expected localhost + to mean "default hostname" without ever standardising it (#1892235) + +* Tue Dec 1 2020 Zbigniew Jędrzejewski-Szmek - 247.1-1 +- Latest stable release +- Fixes #1902819. +- Files to configure networking with systemd-networkd in a VM or container are + moved to systemd-networkd subpackage. (They were previously in the -container + subpackage, which is for container/VM management.) + +* Thu Nov 26 2020 Zbigniew Jędrzejewski-Szmek - 247-1 +- Update to the latest version +- #1900878 should be fixed * Thu Nov 19 2020 Chris Down - 246.1-1.fb5 - Updated version of PR #17495 to fix program leak @@ -841,12 +927,68 @@ fi - Backport PR #17422 to clean up cgroups more reliably after exit - Backport PR #17497 to add FixedRandomDelay= support +* Tue Oct 20 2020 Zbigniew Jędrzejewski-Szmek - 247~rc2 +- New upstream pre-release. See + https://github.com/systemd/systemd/blob/v247-rc1/NEWS. + Many smaller and bigger improvements and features are introduced. + (#1885101, #1890632, #1879216) + + A backwards-incompatible change affects PCI network devices which + are connected through a bridge which is itself associated with a + slot. When more than one device was associated with the same slot, + one of the devices would pseudo-randomly get named after the slot. + That name is now not generated at all. This changed behaviour is + causes the net naming scheme to be changed to "v247". To restore + previous behaviour, specify net.naming-scheme=v245. + + systemd-oomd is built, but should not be considered "production + ready" at this point. Testing and bug reports are welcome. + +* Wed Sep 30 2020 Dusty Mabe - 246.6-3 +- Try to make files in subpackages (especially the networkd subpackage) + more appropriate. + +* Thu Sep 24 2020 Filipe Brandenburger - 246.6-2 +- Build a package with standalone binaries for non-systemd systems. + For now, only systemd-sysusers is included. + +* Thu Sep 24 2020 Christian Glombek - 246.6-2 +- Split out networkd sub-package and add to main package as recommended dependency + +* Sun Sep 20 2020 Zbigniew Jędrzejewski-Szmek - 246.6-1 +- Update to latest stable release (various minor fixes: manager, + networking, bootct, kernel-install, systemd-dissect, systemd-homed, + fstab-generator, documentation) (#1876905) +- Do not fail in test because of kernel bug (#1803070) + * Fri Sep 18 2020 Anita Zhang - 246.1-1.fb3 - Backport PR #16838 and #16857 to improve $PATH handling - Backport PR #16940 to fix ECONN handling in sockets - Backport PR #17031 to fix rate limiting on units in restart loop - Backport PR #17082 to get nspawn TTY tweaks +* Sun Sep 13 2020 Zbigniew Jędrzejewski-Szmek - 246.5-1 +- Update to latest stable release (a bunch of small network-related + fixes in systemd-networkd and socket handling, documentation updates, + a bunch of fixes for error handling). +- Also remove existing file when creating /etc/resolv.conf symlink + upon installation (#1873856 again) + +* Wed Sep 2 2020 Zbigniew Jędrzejewski-Szmek - 246.4-1 +- Update to latest stable version: a rework of how the unit cache mtime works + (hopefully #1872068, #1871327, #1867930), plus various fixes to + systemd-resolved, systemd-dissect, systemd-analyze, systemd-ask-password-agent, + systemd-networkd, systemd-homed, systemd-machine-id-setup, presets for + instantiated units, documentation and shell completions. +- Create /etc/resolv.conf symlink upon installation (#1873856) +- Move nss-mdns before nss-resolve in /etc/nsswitch.conf and disable + mdns by default in systemd-resolved (#1867830) + +* Wed Aug 26 2020 Zbigniew Jędrzejewski-Szmek - 246.3-1 +- Update to bugfix version (some networkd fixes, minor documentation + fixes, relax handling of various error conditions, other fixlets for + bugs without bugzilla numbers). + * Tue Aug 18 2020 Anita Zhang - 246.1-1.fb2 - Gate "Obsoletes: systemd < 245.6-1" out due to dependency issues on Facebook systems