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