From 9ab0c50975feeee399ced5d356cc79b9c1a9ce69 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 06 2019 13:04:57 +0000 Subject: import systemd-219-67.el7_7.1 --- diff --git a/SOURCES/0745-fix-mis-merge.patch b/SOURCES/0745-fix-mis-merge.patch index d7a8c56..19784d2 100644 --- a/SOURCES/0745-fix-mis-merge.patch +++ b/SOURCES/0745-fix-mis-merge.patch @@ -1,4 +1,4 @@ -From 9012a119379d26cefe777c26a88429eb9d0992bd Mon Sep 17 00:00:00 2001 +From 702a5878c3cce3da02403b29ac6e7b8317857dec Mon Sep 17 00:00:00 2001 From: David Tardon Date: Thu, 30 May 2019 13:40:23 +0200 Subject: [PATCH] fix mis-merge @@ -11,7 +11,7 @@ Resolves: #1714503 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/service.c b/src/core/service.c -index 06b39e3..93e4759 100644 +index 06b39e3a5a..93e4759171 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -3046,7 +3046,7 @@ static void service_notify_message( @@ -23,6 +23,3 @@ index 06b39e3..93e4759 100644 _cleanup_free_ char *cc = NULL; cc = strv_join(tags, ", "); --- -2.21.0 - diff --git a/SOURCES/0746-fs-util-chase_symlinks-prevent-double-free.patch b/SOURCES/0746-fs-util-chase_symlinks-prevent-double-free.patch index 963bf5a..b735fae 100644 --- a/SOURCES/0746-fs-util-chase_symlinks-prevent-double-free.patch +++ b/SOURCES/0746-fs-util-chase_symlinks-prevent-double-free.patch @@ -1,4 +1,4 @@ -From 1ca90fdce3a3d2320c88451242310ab871fc099b Mon Sep 17 00:00:00 2001 +From e4834c7be945dfbb0a6d7f13c736924bf9489cd2 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Sun, 21 Jan 2018 19:19:25 +0900 Subject: [PATCH] fs-util: chase_symlinks(): prevent double free @@ -13,7 +13,7 @@ Resolves: #1714782 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/util.c b/src/shared/util.c -index 354d15f..07de902 100644 +index 354d15ff18..07de902aaf 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -9414,8 +9414,6 @@ int chase_symlinks(const char *path, const char *original_root, unsigned flags, @@ -34,6 +34,3 @@ index 354d15f..07de902 100644 /* Note that we do not revalidate the root, we take it as is. */ if (isempty(root)) done = NULL; --- -2.21.0 - diff --git a/SOURCES/0747-return-error-value-on-failure.patch b/SOURCES/0747-return-error-value-on-failure.patch new file mode 100644 index 0000000..573bdfa --- /dev/null +++ b/SOURCES/0747-return-error-value-on-failure.patch @@ -0,0 +1,39 @@ +From 0ee2318c1bc5f13904b8f60e3826eadfe2b7c66f Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Thu, 4 Jul 2019 15:57:23 +0200 +Subject: [PATCH] return error value on failure + +Regression from commit c0f32feb77768aa76d8c813471b3484c93bc2651 . + +(cherry picked from commit e4a25c5d867e6ed832a077c32f3555bcd49ef8a6) + +Resolves: #1729226 +--- + src/core/service.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index 93e4759171..957c6f37cc 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -750,9 +750,9 @@ static int service_load_pid_file(Service *s, bool may_warn) { + + fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL); + if (fd == -EPERM) +- return log_unit_full(UNIT(s)->id, prio, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file); ++ return log_unit_full_errno(UNIT(s)->id, prio, fd, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file); + if (fd < 0) +- return log_unit_full(UNIT(s)->id, prio, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); ++ return log_unit_full_errno(UNIT(s)->id, prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + + /* Let's read the PID file now that we chased it down. But we need to convert the O_PATH fd chase_symlinks() returned us into a proper fd first. */ + xsprintf(procfs, "/proc/self/fd/%i", fd); +@@ -762,7 +762,7 @@ static int service_load_pid_file(Service *s, bool may_warn) { + + r = parse_pid(k, &pid); + if (r < 0) +- return log_unit_full(UNIT(s)->id, prio, "Failed to parse PID from file %s: %m", s->pid_file); ++ return log_unit_full_errno(UNIT(s)->id, prio, r, "Failed to parse PID from file %s: %m", s->pid_file); + + if (s->main_pid_known && pid == s->main_pid) + return 0; diff --git a/SOURCES/0748-revert-local-changes-made-during-backport-of-the-tes.patch b/SOURCES/0748-revert-local-changes-made-during-backport-of-the-tes.patch new file mode 100644 index 0000000..4bad426 --- /dev/null +++ b/SOURCES/0748-revert-local-changes-made-during-backport-of-the-tes.patch @@ -0,0 +1,31 @@ +From 067cc9cc451ef4b98f451bf3a67c10660749ddd0 Mon Sep 17 00:00:00 2001 +From: David Tardon +Date: Wed, 10 Jul 2019 09:48:51 +0200 +Subject: [PATCH] revert local changes made during backport of the test + +(cherry picked from commit 225a458ec4c1bee97d0cee13895977614fd8cc16) + +Related: #1729226 +--- + test/TEST-20-MAINPIDGAMES/testsuite.sh | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/test/TEST-20-MAINPIDGAMES/testsuite.sh b/test/TEST-20-MAINPIDGAMES/testsuite.sh +index d4ad63865c..8b0b664652 100755 +--- a/test/TEST-20-MAINPIDGAMES/testsuite.sh ++++ b/test/TEST-20-MAINPIDGAMES/testsuite.sh +@@ -175,12 +175,10 @@ ExecStart=/dev/shm/mainpid3.sh + EOF + + systemctl daemon-reload +-systemctl start mainpidsh3.service ++! systemctl start mainpidsh3.service + + # Test that this failed due to timeout, and not some other error +-# test `systemctl_show_value -p Result mainpidsh3.service` = timeout +-# Just check that there is no MainPID => the pid file was ignored +-test `systemctl_show_value -p MainPID mainpidsh3.service` -eq 0 ++test `systemctl_show_value -p Result mainpidsh3.service` = timeout + + systemd-analyze set-log-level info + diff --git a/SOURCES/0749-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch b/SOURCES/0749-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch new file mode 100644 index 0000000..0266c15 --- /dev/null +++ b/SOURCES/0749-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch @@ -0,0 +1,75 @@ +From d7eac3e0ae20510e2737dc4e23975391fef5ece3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Michal=20Koutn=C3=BD?= +Date: Tue, 16 Jan 2018 19:22:46 +0100 +Subject: [PATCH] core/timer: Prevent timer looping when unit cannot start + +When a unit job finishes early (e.g. when fork(2) fails) triggered unit goes +through states + stopped->failed (or failed->failed), +in case a ExecStart= command fails unit passes through + stopped->starting->failed. + +The former transition doesn't result in unit active/inactive timestamp being +updated and timer (OnUnitActiveSec= or OnUnitInactiveSec=) would use an expired +timestamp triggering immediately again (repeatedly). + +This patch exploits timer's last trigger timestamp to ensure the timer isn't +triggered more frequently than OnUnitActiveSec=/OnUnitInactiveSec= period. + +Steps to reproduce: + +0) Create sample units: + +cat >~/.config/systemd/user/looper.service <~/.config/systemd/user/looper.timer <last_trigger.monotonic); + + break; + +@@ -428,6 +429,7 @@ static void timer_enter_waiting(Timer *t, bool initial) { + + if (base <= 0) + continue; ++ base = MAX(base, t->last_trigger.monotonic); + + break; + diff --git a/SOURCES/0750-core-add-a-Requires-dependency-between-units-and-the.patch b/SOURCES/0750-core-add-a-Requires-dependency-between-units-and-the.patch new file mode 100644 index 0000000..5bdd59c --- /dev/null +++ b/SOURCES/0750-core-add-a-Requires-dependency-between-units-and-the.patch @@ -0,0 +1,40 @@ +From e932760979f8658ff62b93b039a98a6d7f0f4656 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 29 Sep 2015 13:06:28 +0200 +Subject: [PATCH] core: add a "Requires=" dependency between units and the + slices they are located in + +We place the processes we fork off in the cgroup anyway, and we probably +shouldn't be able to get that far if we couldn't set up the slice due to +resource problems or unmet conditions. Hence upgrade the dependency +between units and the slices they are located in from Wants= to +Requires=. + +(cherry picked from commit 8c8da0e0cb498245c765732cf9caa081a70c560f) +(cherry picked from commit 0600681f04e3818282a2d518ec3e6afee85f7978) + +Related: #1729228 +--- + src/core/unit.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 37fac8db3a..1dff541ac3 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -1113,12 +1113,12 @@ static int unit_add_slice_dependencies(Unit *u) { + return 0; + + if (UNIT_ISSET(u->slice)) +- return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_WANTS, UNIT_DEREF(u->slice), true); ++ return unit_add_two_dependencies(u, UNIT_AFTER, UNIT_REQUIRES, UNIT_DEREF(u->slice), true); + +- if (streq(u->id, SPECIAL_ROOT_SLICE)) ++ if (unit_has_name(u, SPECIAL_ROOT_SLICE)) + return 0; + +- return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_WANTS, SPECIAL_ROOT_SLICE, NULL, true); ++ return unit_add_two_dependencies_by_name(u, UNIT_AFTER, UNIT_REQUIRES, SPECIAL_ROOT_SLICE, NULL, true); + } + + static int unit_add_mount_dependencies(Unit *u) { diff --git a/SOURCES/0751-core-rerun-GC-logic-for-a-unit-that-loses-a-referenc.patch b/SOURCES/0751-core-rerun-GC-logic-for-a-unit-that-loses-a-referenc.patch new file mode 100644 index 0000000..e871262 --- /dev/null +++ b/SOURCES/0751-core-rerun-GC-logic-for-a-unit-that-loses-a-referenc.patch @@ -0,0 +1,36 @@ +From 2175fc04df0f8e272cbff7540acd38eced9c63d7 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 29 Apr 2016 11:18:53 +0200 +Subject: [PATCH] core: rerun GC logic for a unit that loses a reference + +Let's make sure when we drop a reference to a unit, that we run the GC queue on +it again. + +This (together with the previous commit) should deal with the GC issues pointed +out in: + +https://github.com/systemd/systemd/pull/2993#issuecomment-215331189 + +(cherry picked from commit b75102e5bf4cf249052d42be955d403e3e03b47c) +(cherry picked from commit 0ace07115f14a57c81afbc9a7e947778a743870e) + +Related: #1729228 +--- + src/core/unit.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 1dff541ac3..b004aa8fcd 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -3145,6 +3145,10 @@ void unit_ref_unset(UnitRef *ref) { + if (!ref->unit) + return; + ++ /* We are about to drop a reference to the unit, make sure the garbage collection has a look at it as it might ++ * be unreferenced now. */ ++ unit_add_to_gc_queue(ref->unit); ++ + LIST_REMOVE(refs, ref->unit->refs, ref); + ref->unit = NULL; + } diff --git a/SOURCES/0752-pid1-rename-unit_check_gc-to-unit_may_gc.patch b/SOURCES/0752-pid1-rename-unit_check_gc-to-unit_may_gc.patch new file mode 100644 index 0000000..cc822f8 --- /dev/null +++ b/SOURCES/0752-pid1-rename-unit_check_gc-to-unit_may_gc.patch @@ -0,0 +1,360 @@ +From cb1a8f709ff3c27fc9f43aa27f985131422795bc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 13 Feb 2018 10:50:13 +0100 +Subject: [PATCH] pid1: rename unit_check_gc to unit_may_gc + +"check" is unclear: what is true, what is false? Let's rename to "can_gc" and +revert the return value ("positive" values are easier to grok). + +v2: +- rename from unit_can_gc to unit_may_gc + +(cherry picked from commit f2f725e5cc950e84ebfd09bd64bc01c0ebdb6734) +(cherry picked from commit 1716821fc5b93667a0bf821b25905de00818aec9) + +Related: #1729228 +--- + src/core/automount.c | 13 ++++++++----- + src/core/manager.c | 2 +- + src/core/mount.c | 9 ++++++--- + src/core/scope.c | 8 ++++---- + src/core/service.c | 8 ++++---- + src/core/socket.c | 6 +++--- + src/core/socket.h | 4 ++-- + src/core/swap.c | 9 ++++++--- + src/core/unit.c | 31 +++++++++++++++++-------------- + src/core/unit.h | 9 ++++----- + 10 files changed, 55 insertions(+), 44 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index 4678bdc7c9..7b9c4aaf1d 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -936,13 +936,16 @@ static const char *automount_sub_state_to_string(Unit *u) { + return automount_state_to_string(AUTOMOUNT(u)->state); + } + +-static bool automount_check_gc(Unit *u) { ++static bool automount_may_gc(Unit *u) { ++ Unit *t; ++ + assert(u); + +- if (!UNIT_TRIGGER(u)) +- return false; ++ t = UNIT_TRIGGER(u); ++ if (!t) ++ return true; + +- return UNIT_VTABLE(UNIT_TRIGGER(u))->check_gc(UNIT_TRIGGER(u)); ++ return UNIT_VTABLE(t)->may_gc(t); + } + + static int automount_dispatch_io(sd_event_source *s, int fd, uint32_t events, void *userdata) { +@@ -1115,7 +1118,7 @@ const UnitVTable automount_vtable = { + .active_state = automount_active_state, + .sub_state_to_string = automount_sub_state_to_string, + +- .check_gc = automount_check_gc, ++ .may_gc = automount_may_gc, + + .reset_failed = automount_reset_failed, + +diff --git a/src/core/manager.c b/src/core/manager.c +index 3bca61d0b1..9dfdd67860 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -871,7 +871,7 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) { + if (u->in_cleanup_queue) + goto bad; + +- if (unit_check_gc(u)) ++ if (!unit_may_gc(u)) + goto good; + + u->gc_marker = gc_marker + GC_OFFSET_IN_PATH; +diff --git a/src/core/mount.c b/src/core/mount.c +index c7aed2333f..8a25ebd163 100644 +--- a/src/core/mount.c ++++ b/src/core/mount.c +@@ -1180,12 +1180,15 @@ _pure_ static const char *mount_sub_state_to_string(Unit *u) { + return mount_state_to_string(MOUNT(u)->state); + } + +-_pure_ static bool mount_check_gc(Unit *u) { ++_pure_ static bool mount_may_gc(Unit *u) { + Mount *m = MOUNT(u); + + assert(m); + +- return m->from_proc_self_mountinfo; ++ if (m->from_proc_self_mountinfo) ++ return false; ++ ++ return true; + } + + static void mount_sigchld_event(Unit *u, pid_t pid, int code, int status) { +@@ -1954,7 +1957,7 @@ const UnitVTable mount_vtable = { + .active_state = mount_active_state, + .sub_state_to_string = mount_sub_state_to_string, + +- .check_gc = mount_check_gc, ++ .may_gc = mount_may_gc, + + .sigchld_event = mount_sigchld_event, + +diff --git a/src/core/scope.c b/src/core/scope.c +index 29954ba285..e9b45aa3f8 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -381,7 +381,7 @@ static int scope_deserialize_item(Unit *u, const char *key, const char *value, F + return 0; + } + +-static bool scope_check_gc(Unit *u) { ++static bool scope_may_gc(Unit *u) { + assert(u); + + /* Never clean up scopes that still have a process around, +@@ -392,10 +392,10 @@ static bool scope_check_gc(Unit *u) { + + r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true); + if (r <= 0) +- return true; ++ return false; + } + +- return false; ++ return true; + } + + static void scope_notify_cgroup_empty_event(Unit *u) { +@@ -547,7 +547,7 @@ const UnitVTable scope_vtable = { + .active_state = scope_active_state, + .sub_state_to_string = scope_sub_state_to_string, + +- .check_gc = scope_check_gc, ++ .may_gc = scope_may_gc, + + .sigchld_event = scope_sigchld_event, + +diff --git a/src/core/service.c b/src/core/service.c +index 957c6f37cc..69ec916f2d 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -2436,7 +2436,7 @@ static const char *service_sub_state_to_string(Unit *u) { + return service_state_to_string(SERVICE(u)->state); + } + +-static bool service_check_gc(Unit *u) { ++static bool service_may_gc(Unit *u) { + Service *s = SERVICE(u); + + assert(s); +@@ -2446,9 +2446,9 @@ static bool service_check_gc(Unit *u) { + if (cgroup_good(s) > 0 || + main_pid_good(s) > 0 || + control_pid_good(s) > 0) +- return true; ++ return false; + +- return false; ++ return true; + } + + _pure_ static bool service_check_snapshot(Unit *u) { +@@ -3461,7 +3461,7 @@ const UnitVTable service_vtable = { + .active_state = service_active_state, + .sub_state_to_string = service_sub_state_to_string, + +- .check_gc = service_check_gc, ++ .may_gc = service_may_gc, + .check_snapshot = service_check_snapshot, + + .sigchld_event = service_sigchld_event, +diff --git a/src/core/socket.c b/src/core/socket.c +index efefe7ce5d..3e4cdd467f 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -2269,12 +2269,12 @@ const char* socket_port_type_to_string(SocketPort *p) { + } + } + +-_pure_ static bool socket_check_gc(Unit *u) { ++_pure_ static bool socket_may_gc(Unit *u) { + Socket *s = SOCKET(u); + + assert(u); + +- return s->n_connections > 0; ++ return s->n_connections == 0; + } + + static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) { +@@ -2713,7 +2713,7 @@ const UnitVTable socket_vtable = { + .active_state = socket_active_state, + .sub_state_to_string = socket_sub_state_to_string, + +- .check_gc = socket_check_gc, ++ .may_gc = socket_may_gc, + + .sigchld_event = socket_sigchld_event, + +diff --git a/src/core/socket.h b/src/core/socket.h +index a2e08998c0..cc1428b3f7 100644 +--- a/src/core/socket.h ++++ b/src/core/socket.h +@@ -114,8 +114,8 @@ struct Socket { + ExecRuntime *exec_runtime; + + /* For Accept=no sockets refers to the one service we'll +- activate. For Accept=yes sockets is either NULL, or filled +- when the next service we spawn. */ ++ * activate. For Accept=yes sockets is either NULL, or filled ++ * to refer to the next service we spawn. */ + UnitRef service; + + SocketState state, deserialized_state; +diff --git a/src/core/swap.c b/src/core/swap.c +index e71de4e657..1f69736aa3 100644 +--- a/src/core/swap.c ++++ b/src/core/swap.c +@@ -949,12 +949,15 @@ _pure_ static const char *swap_sub_state_to_string(Unit *u) { + return swap_state_to_string(SWAP(u)->state); + } + +-_pure_ static bool swap_check_gc(Unit *u) { ++_pure_ static bool swap_may_gc(Unit *u) { + Swap *s = SWAP(u); + + assert(s); + +- return s->from_proc_swaps; ++ if (s->from_proc_swaps) ++ return false; ++ ++ return true; + } + + static void swap_sigchld_event(Unit *u, pid_t pid, int code, int status) { +@@ -1497,7 +1500,7 @@ const UnitVTable swap_vtable = { + .active_state = swap_active_state, + .sub_state_to_string = swap_sub_state_to_string, + +- .check_gc = swap_check_gc, ++ .may_gc = swap_may_gc, + + .sigchld_event = swap_sigchld_event, + +diff --git a/src/core/unit.c b/src/core/unit.c +index b004aa8fcd..1b8ec9a20e 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -282,15 +282,19 @@ int unit_set_description(Unit *u, const char *description) { + return 0; + } + +-bool unit_check_gc(Unit *u) { ++bool unit_may_gc(Unit *u) { + UnitActiveState state; + assert(u); + ++ /* Checks whether the unit is ready to be unloaded for garbage collection. ++ * Returns true when the unit may be collected, and false if there's some ++ * reason to keep it loaded. */ ++ + if (u->job) +- return true; ++ return false; + + if (u->nop_job) +- return true; ++ return false; + + state = unit_active_state(u); + +@@ -303,22 +307,21 @@ bool unit_check_gc(Unit *u) { + /* But we keep the unit object around for longer when it is + * referenced or configured to not be gc'ed */ + if (state != UNIT_INACTIVE) +- return true; ++ return false; + + if (UNIT_VTABLE(u)->no_gc) +- return true; ++ return false; + + if (u->no_gc) +- return true; ++ return false; + + if (u->refs) +- return true; ++ return false; + +- if (UNIT_VTABLE(u)->check_gc) +- if (UNIT_VTABLE(u)->check_gc(u)) +- return true; ++ if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u)) ++ return false; + +- return false; ++ return true; + } + + void unit_add_to_load_queue(Unit *u) { +@@ -348,7 +351,7 @@ void unit_add_to_gc_queue(Unit *u) { + if (u->in_gc_queue || u->in_cleanup_queue) + return; + +- if (unit_check_gc(u)) ++ if (!unit_may_gc(u)) + return; + + LIST_PREPEND(gc_queue, u->manager->gc_queue, u); +@@ -888,7 +891,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + "%s\tActive Enter Timestamp: %s\n" + "%s\tActive Exit Timestamp: %s\n" + "%s\tInactive Enter Timestamp: %s\n" +- "%s\tGC Check Good: %s\n" ++ "%s\tMay GC: %s\n" + "%s\tNeed Daemon Reload: %s\n" + "%s\tTransient: %s\n" + "%s\tSlice: %s\n" +@@ -905,7 +908,7 @@ void unit_dump(Unit *u, FILE *f, const char *prefix) { + prefix, strna(format_timestamp(timestamp2, sizeof(timestamp2), u->active_enter_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp3, sizeof(timestamp3), u->active_exit_timestamp.realtime)), + prefix, strna(format_timestamp(timestamp4, sizeof(timestamp4), u->inactive_enter_timestamp.realtime)), +- prefix, yes_no(unit_check_gc(u)), ++ prefix, yes_no(unit_may_gc(u)), + prefix, yes_no(unit_need_daemon_reload(u)), + prefix, yes_no(u->transient), + prefix, strna(unit_slice_name(u)), +diff --git a/src/core/unit.h b/src/core/unit.h +index 091ef7596e..3f411a1793 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -353,10 +353,9 @@ struct UnitVTable { + * unit is in. */ + const char* (*sub_state_to_string)(Unit *u); + +- /* Return true when there is reason to keep this entry around +- * even nothing references it and it isn't active in any +- * way */ +- bool (*check_gc)(Unit *u); ++ /* Return false when there is a reason to prevent this unit from being gc'ed ++ * even though nothing references it and it isn't active in any way. */ ++ bool (*may_gc)(Unit *u); + + /* When the unit is not running and no job for it queued we + * shall release its runtime resources */ +@@ -496,7 +495,7 @@ int unit_add_exec_dependencies(Unit *u, ExecContext *c); + int unit_choose_id(Unit *u, const char *name); + int unit_set_description(Unit *u, const char *description); + +-bool unit_check_gc(Unit *u); ++bool unit_may_gc(Unit *u); + + void unit_add_to_load_queue(Unit *u); + void unit_add_to_dbus_queue(Unit *u); diff --git a/SOURCES/0753-pid1-include-the-source-unit-in-UnitRef.patch b/SOURCES/0753-pid1-include-the-source-unit-in-UnitRef.patch new file mode 100644 index 0000000..e90ac06 --- /dev/null +++ b/SOURCES/0753-pid1-include-the-source-unit-in-UnitRef.patch @@ -0,0 +1,276 @@ +From c6da3d5d824f7b125b3fd95a961eca98db7febf7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 13 Feb 2018 13:12:43 +0100 +Subject: [PATCH] pid1: include the source unit in UnitRef + +No functional change. + +The source unit manages the reference. It allocates the UnitRef structure and +registers it in the target unit, and then the reference must be destroyed +before the source unit is destroyed. Thus, is should be OK to include the +pointer to the source unit, it should be live as long as the reference exists. + +v2: +- rename refs to refs_by_target + +(cherry picked from commit 7f7d01ed5804afef220ebdb29f22d8177d0d3a5c) +(cherry picked from commit ff80bfd94181327a5f8e0fbd70b9b7afe0c5545c) + +Related: #1729228 +--- + src/core/busname.c | 2 +- + src/core/dbus-manager.c | 2 +- + src/core/dbus-unit.c | 2 +- + src/core/load-fragment.c | 6 +++--- + src/core/service.c | 2 +- + src/core/slice.c | 2 +- + src/core/socket.c | 4 ++-- + src/core/unit.c | 35 ++++++++++++++++++----------------- + src/core/unit.h | 12 ++++++------ + 9 files changed, 34 insertions(+), 33 deletions(-) + +diff --git a/src/core/busname.c b/src/core/busname.c +index a5e659049d..97886f1e05 100644 +--- a/src/core/busname.c ++++ b/src/core/busname.c +@@ -175,7 +175,7 @@ static int busname_add_extras(BusName *n) { + if (r < 0) + return r; + +- unit_ref_set(&n->service, x); ++ unit_ref_set(&n->service, u, x); + } + + r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(n->service), true); +diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c +index 1766163b33..8267d44e1a 100644 +--- a/src/core/dbus-manager.c ++++ b/src/core/dbus-manager.c +@@ -649,7 +649,7 @@ static int transient_unit_from_message( + u->fragment_path || + u->source_path || + !strv_isempty(u->dropin_paths) || +- u->refs || ++ u->refs_by_target || + set_size(u->dependencies[UNIT_REFERENCED_BY]) > 0) + return sd_bus_error_setf(error, BUS_ERROR_UNIT_EXISTS, "Unit %s already exists.", name); + +diff --git a/src/core/dbus-unit.c b/src/core/dbus-unit.c +index f0f75e01b0..77073308c8 100644 +--- a/src/core/dbus-unit.c ++++ b/src/core/dbus-unit.c +@@ -967,7 +967,7 @@ static int bus_unit_set_transient_property( + return -EINVAL; + + if (mode != UNIT_CHECK) { +- unit_ref_set(&u->slice, slice); ++ unit_ref_set(&u->slice, u, slice); + unit_write_drop_in_private_format(u, mode, name, "Slice=%s\n", s); + } + } +diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c +index f3d0851fe2..1721fea8f3 100644 +--- a/src/core/load-fragment.c ++++ b/src/core/load-fragment.c +@@ -1836,7 +1836,7 @@ int config_parse_socket_service( + return 0; + } + +- unit_ref_set(&s->service, x); ++ unit_ref_set(&s->service, UNIT(s), x); + + return 0; + } +@@ -2006,7 +2006,7 @@ int config_parse_busname_service( + return 0; + } + +- unit_ref_set(&n->service, x); ++ unit_ref_set(&n->service, UNIT(n), x); + + return 0; + } +@@ -2933,7 +2933,7 @@ int config_parse_unit_slice( + return 0; + } + +- unit_ref_set(&u->slice, slice); ++ unit_ref_set(&u->slice, u, slice); + return 0; + } + +diff --git a/src/core/service.c b/src/core/service.c +index 69ec916f2d..eaa588863f 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -3299,7 +3299,7 @@ int service_set_socket_fd(Service *s, int fd, Socket *sock, bool selinux_context + s->socket_fd = fd; + s->socket_fd_selinux_context_net = selinux_context_net; + +- unit_ref_set(&s->accept_socket, UNIT(sock)); ++ unit_ref_set(&s->accept_socket, UNIT(s), UNIT(sock)); + + return unit_add_two_dependencies(UNIT(sock), UNIT_BEFORE, UNIT_TRIGGERS, UNIT(s), false); + } +diff --git a/src/core/slice.c b/src/core/slice.c +index 1cce3e1217..0985a65286 100644 +--- a/src/core/slice.c ++++ b/src/core/slice.c +@@ -76,7 +76,7 @@ static int slice_add_parent_slice(Slice *s) { + if (r < 0) + return r; + +- unit_ref_set(&UNIT(s)->slice, parent); ++ unit_ref_set(&UNIT(s)->slice, UNIT(s), parent); + return 0; + } + +diff --git a/src/core/socket.c b/src/core/socket.c +index 3e4cdd467f..8489575de6 100644 +--- a/src/core/socket.c ++++ b/src/core/socket.c +@@ -208,7 +208,7 @@ int socket_instantiate_service(Socket *s) { + return r; + + u->no_gc = true; +- unit_ref_set(&s->service, u); ++ unit_ref_set(&s->service, UNIT(s), u); + + return unit_add_two_dependencies(UNIT(s), UNIT_BEFORE, UNIT_TRIGGERS, u, false); + } +@@ -313,7 +313,7 @@ static int socket_add_extras(Socket *s) { + if (r < 0) + return r; + +- unit_ref_set(&s->service, x); ++ unit_ref_set(&s->service, u, x); + } + + r = unit_add_two_dependencies(u, UNIT_BEFORE, UNIT_TRIGGERS, UNIT_DEREF(s->service), true); +diff --git a/src/core/unit.c b/src/core/unit.c +index 1b8ec9a20e..5376ef862f 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -315,7 +315,7 @@ bool unit_may_gc(Unit *u) { + if (u->no_gc) + return false; + +- if (u->refs) ++ if (u->refs_by_target) + return false; + + if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u)) +@@ -553,9 +553,8 @@ void unit_free(Unit *u) { + condition_free_list(u->asserts); + + unit_ref_unset(&u->slice); +- +- while (u->refs) +- unit_ref_unset(u->refs); ++ while (u->refs_by_target) ++ unit_ref_unset(u->refs_by_target); + + free(u); + } +@@ -737,8 +736,8 @@ int unit_merge(Unit *u, Unit *other) { + return r; + + /* Redirect all references */ +- while (other->refs) +- unit_ref_set(other->refs, u); ++ while (other->refs_by_target) ++ unit_ref_set(other->refs_by_target, other->refs_by_target->source, u); + + /* Merge dependencies */ + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) +@@ -2493,7 +2492,7 @@ int unit_add_default_slice(Unit *u, CGroupContext *c) { + if (r < 0) + return r; + +- unit_ref_set(&u->slice, slice); ++ unit_ref_set(&u->slice, u, slice); + return 0; + } + +@@ -3130,30 +3129,32 @@ int unit_get_unit_file_preset(Unit *u) { + return u->unit_file_preset; + } + +-Unit* unit_ref_set(UnitRef *ref, Unit *u) { ++Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target) { + assert(ref); +- assert(u); ++ assert(source); ++ assert(target); + +- if (ref->unit) ++ if (ref->target) + unit_ref_unset(ref); + +- ref->unit = u; +- LIST_PREPEND(refs, u->refs, ref); +- return u; ++ ref->source = source; ++ ref->target = target; ++ LIST_PREPEND(refs_by_target, target->refs_by_target, ref); ++ return target; + } + + void unit_ref_unset(UnitRef *ref) { + assert(ref); + +- if (!ref->unit) ++ if (!ref->target) + return; + + /* We are about to drop a reference to the unit, make sure the garbage collection has a look at it as it might + * be unreferenced now. */ +- unit_add_to_gc_queue(ref->unit); ++ unit_add_to_gc_queue(ref->target); + +- LIST_REMOVE(refs, ref->unit->refs, ref); +- ref->unit = NULL; ++ LIST_REMOVE(refs_by_target, ref->target->refs_by_target, ref); ++ ref->source = ref->target = NULL; + } + + int unit_patch_contexts(Unit *u) { +diff --git a/src/core/unit.h b/src/core/unit.h +index 3f411a1793..a6e21d60ce 100644 +--- a/src/core/unit.h ++++ b/src/core/unit.h +@@ -84,8 +84,8 @@ struct UnitRef { + * that we can merge two units if necessary and correct all + * references to them */ + +- Unit* unit; +- LIST_FIELDS(UnitRef, refs); ++ Unit *source, *target; ++ LIST_FIELDS(UnitRef, refs_by_target); + }; + + struct Unit { +@@ -125,7 +125,7 @@ struct Unit { + char *job_timeout_reboot_arg; + + /* References to this */ +- LIST_HEAD(UnitRef, refs); ++ LIST_HEAD(UnitRef, refs_by_target); + + /* Conditions to check */ + LIST_HEAD(Condition, conditions); +@@ -591,11 +591,11 @@ void unit_trigger_notify(Unit *u); + UnitFileState unit_get_unit_file_state(Unit *u); + int unit_get_unit_file_preset(Unit *u); + +-Unit* unit_ref_set(UnitRef *ref, Unit *u); ++Unit* unit_ref_set(UnitRef *ref, Unit *source, Unit *target); + void unit_ref_unset(UnitRef *ref); + +-#define UNIT_DEREF(ref) ((ref).unit) +-#define UNIT_ISSET(ref) (!!(ref).unit) ++#define UNIT_DEREF(ref) ((ref).target) ++#define UNIT_ISSET(ref) (!!(ref).target) + + int unit_patch_contexts(Unit *u); + diff --git a/SOURCES/0754-pid1-fix-collection-of-cycles-of-units-which-referen.patch b/SOURCES/0754-pid1-fix-collection-of-cycles-of-units-which-referen.patch new file mode 100644 index 0000000..d6ac1bd --- /dev/null +++ b/SOURCES/0754-pid1-fix-collection-of-cycles-of-units-which-referen.patch @@ -0,0 +1,76 @@ +From 98774bdfb6d40e5b7d41b86238ee2d98ff12cb69 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 13 Feb 2018 14:37:11 +0100 +Subject: [PATCH] pid1: fix collection of cycles of units which reference one + another + +A .socket will reference a .service unit, by registering a UnitRef with the +.service unit. If this .service unit has the .socket unit listed in Wants or +Sockets or such, a cycle will be created. We would not free this cycle +properly, because we treated any unit with non-empty refs as uncollectable. To +solve this issue, treats refs with UnitRef in u->refs_by_target similarly to +the refs in u->dependencies, and check if the "other" unit is known to be +needed. If it is not needed, do not treat the reference from it as preventing +the unit we are looking at from being freed. + +(cherry picked from commit 2641f02e23ac7d5385db7f932aff221a063f245e) +(cherry picked from commit 703cc4991049cdf3ad3506e432cda982b3b3b007) + +Resolves: #1729228 +--- + src/core/manager.c | 14 ++++++++++++++ + src/core/unit.c | 9 +++++---- + 2 files changed, 19 insertions(+), 4 deletions(-) + +diff --git a/src/core/manager.c b/src/core/manager.c +index 9dfdd67860..fdbb3c0fd9 100644 +--- a/src/core/manager.c ++++ b/src/core/manager.c +@@ -888,6 +888,20 @@ static void unit_gc_sweep(Unit *u, unsigned gc_marker) { + is_bad = false; + } + ++ if (u->refs_by_target) { ++ const UnitRef *ref; ++ ++ LIST_FOREACH(refs_by_target, ref, u->refs_by_target) { ++ unit_gc_sweep(ref->source, gc_marker); ++ ++ if (ref->source->gc_marker == gc_marker + GC_OFFSET_GOOD) ++ goto good; ++ ++ if (ref->source->gc_marker != gc_marker + GC_OFFSET_BAD) ++ is_bad = false; ++ } ++ } ++ + if (is_bad) + goto bad; + +diff --git a/src/core/unit.c b/src/core/unit.c +index 5376ef862f..2204be26d2 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -288,7 +288,11 @@ bool unit_may_gc(Unit *u) { + + /* Checks whether the unit is ready to be unloaded for garbage collection. + * Returns true when the unit may be collected, and false if there's some +- * reason to keep it loaded. */ ++ * reason to keep it loaded. ++ * ++ * References from other units are *not* checked here. Instead, this is done ++ * in unit_gc_sweep(), but using markers to properly collect dependency loops. ++ */ + + if (u->job) + return false; +@@ -315,9 +319,6 @@ bool unit_may_gc(Unit *u) { + if (u->no_gc) + return false; + +- if (u->refs_by_target) +- return false; +- + if (UNIT_VTABLE(u)->may_gc && !UNIT_VTABLE(u)->may_gc(u)) + return false; + diff --git a/SOURCES/0755-pid1-free-basic-unit-information-at-the-very-end-bef.patch b/SOURCES/0755-pid1-free-basic-unit-information-at-the-very-end-bef.patch new file mode 100644 index 0000000..3d0fc44 --- /dev/null +++ b/SOURCES/0755-pid1-free-basic-unit-information-at-the-very-end-bef.patch @@ -0,0 +1,58 @@ +From 20d684011c93bed4b45c736ac1f9104983a090dc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Wed, 14 Feb 2018 00:01:05 +0100 +Subject: [PATCH] pid1: free basic unit information at the very end, before + freeing the unit + +We would free stuff like the names of the unit first, and then recurse +into other structures to remove the unit from there. Technically this +was OK, since the code did not access the name, but this makes debugging +harder. And if any log messages are added in any of those functions, they +are likely to access u->id and such other basic information about the unit. +So let's move the removal of this "basic" information towards the end +of unit_free(). + +(cherry picked from commit a946fa9bb968ac197d7a99970e27388b751dca94) +(cherry picked from commit 42a93a826cd726d1e4d3ea2c8cb347cec2f0dabe) + +Related: #1729228 +--- + src/core/unit.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 2204be26d2..63f00acc0a 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -537,6 +537,15 @@ void unit_free(Unit *u) { + set_remove(u->manager->failed_units, u); + set_remove(u->manager->startup_units, u); + ++ unit_unwatch_all_pids(u); ++ ++ unit_ref_unset(&u->slice); ++ while (u->refs_by_target) ++ unit_ref_unset(u->refs_by_target); ++ ++ condition_free_list(u->conditions); ++ condition_free_list(u->asserts); ++ + free(u->description); + strv_free(u->documentation); + free(u->fragment_path); +@@ -548,15 +557,6 @@ void unit_free(Unit *u) { + + set_free_free(u->names); + +- unit_unwatch_all_pids(u); +- +- condition_free_list(u->conditions); +- condition_free_list(u->asserts); +- +- unit_ref_unset(&u->slice); +- while (u->refs_by_target) +- unit_ref_unset(u->refs_by_target); +- + free(u); + } + diff --git a/SOURCES/0756-pid1-properly-remove-references-to-the-unit-from-gc-.patch b/SOURCES/0756-pid1-properly-remove-references-to-the-unit-from-gc-.patch new file mode 100644 index 0000000..b4c8472 --- /dev/null +++ b/SOURCES/0756-pid1-properly-remove-references-to-the-unit-from-gc-.patch @@ -0,0 +1,79 @@ +From 019b19130bcba9d88c0328b40f2639e6ebbb513c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= +Date: Tue, 13 Feb 2018 23:57:43 +0100 +Subject: [PATCH] pid1: properly remove references to the unit from gc queue + during final cleanup + +When various references to the unit were dropped during cleanup in unit_free(), +add_to_gc_queue() could be called on this unit. If the unit was previously in +the gc queue (at the time when unit_free() was called on it), this wouldn't +matter, because it'd have in_gc_queue still set even though it was already +removed from the queue. But if it wasn't set, then the unit could be added to +the queue. Then after unit_free() would deallocate the unit, we would be left +with a dangling pointer in gc_queue. + +A unit could be added to the gc queue in two places called from unit_free(): +in the job_install calls, and in unit_ref_unset(). The first was OK, because +it was above the LIST_REMOVE(gc_queue,...) call, but the second was not, because +it was after that. Move the all LIST_REMOVE() calls down. + +(cherry picked from commit 1bdf2790025e661e41894129eb390bb032b88585) +(cherry picked from commit 8f1df942e2237124f7559176081af7ac631d3422) + +Related: #1729228 +--- + src/core/unit.c | 34 +++++++++++++++++----------------- + 1 file changed, 17 insertions(+), 17 deletions(-) + +diff --git a/src/core/unit.c b/src/core/unit.c +index 63f00acc0a..def36a0930 100644 +--- a/src/core/unit.c ++++ b/src/core/unit.c +@@ -506,23 +506,6 @@ void unit_free(Unit *u) { + for (d = 0; d < _UNIT_DEPENDENCY_MAX; d++) + bidi_set_free(u, u->dependencies[d]); + +- if (u->type != _UNIT_TYPE_INVALID) +- LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u); +- +- if (u->in_load_queue) +- LIST_REMOVE(load_queue, u->manager->load_queue, u); +- +- if (u->in_dbus_queue) +- LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); +- +- if (u->in_cleanup_queue) +- LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u); +- +- if (u->in_gc_queue) { +- LIST_REMOVE(gc_queue, u->manager->gc_queue, u); +- u->manager->n_in_gc_queue--; +- } +- + if (u->in_target_deps_queue) + LIST_REMOVE(target_deps_queue, u->manager->target_deps_queue, u); + +@@ -543,6 +526,23 @@ void unit_free(Unit *u) { + while (u->refs_by_target) + unit_ref_unset(u->refs_by_target); + ++ if (u->type != _UNIT_TYPE_INVALID) ++ LIST_REMOVE(units_by_type, u->manager->units_by_type[u->type], u); ++ ++ if (u->in_load_queue) ++ LIST_REMOVE(load_queue, u->manager->load_queue, u); ++ ++ if (u->in_dbus_queue) ++ LIST_REMOVE(dbus_queue, u->manager->dbus_unit_queue, u); ++ ++ if (u->in_cleanup_queue) ++ LIST_REMOVE(cleanup_queue, u->manager->cleanup_queue, u); ++ ++ if (u->in_gc_queue) { ++ LIST_REMOVE(gc_queue, u->manager->gc_queue, u); ++ u->manager->n_in_gc_queue--; ++ } ++ + condition_free_list(u->conditions); + condition_free_list(u->asserts); + diff --git a/SOURCES/0757-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch b/SOURCES/0757-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch new file mode 100644 index 0000000..4983c8f --- /dev/null +++ b/SOURCES/0757-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch @@ -0,0 +1,59 @@ +From 625b30e09d0090f81722aa8f02e7057839dfcf4f Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 9 Feb 2018 17:05:17 +0100 +Subject: [PATCH] service: relax PID file symlink chain checks a bit (#8133) + +Let's read the PID file after all if there's a potentially unsafe +symlink chain in place. But if we do, then refuse taking the PID if its +outside of the cgroup. + +Fixes: #8085 + +(cherry picked from commit 73969ab61c39357e6892747e43307fbf07cafbed) +(cherry picked from commit ce87ed7b47c61e649a0f9da39d272631b9524740) + +Resolves: #1729414 +--- + src/core/service.c | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/src/core/service.c b/src/core/service.c +index eaa588863f..6b61ccac18 100644 +--- a/src/core/service.c ++++ b/src/core/service.c +@@ -736,6 +736,7 @@ static int service_is_suitable_main_pid(Service *s, pid_t pid, int prio) { + + static int service_load_pid_file(Service *s, bool may_warn) { + char procfs[sizeof("/proc/self/fd/") - 1 + DECIMAL_STR_MAX(int)]; ++ bool questionable_pid_file = false; + _cleanup_free_ char *k = NULL; + _cleanup_close_ int fd = -1; + int r, prio; +@@ -749,8 +750,13 @@ static int service_load_pid_file(Service *s, bool may_warn) { + prio = may_warn ? LOG_INFO : LOG_DEBUG; + + fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN|CHASE_SAFE, NULL); +- if (fd == -EPERM) +- return log_unit_full_errno(UNIT(s)->id, prio, fd, "Permission denied while opening PID file or unsafe symlink chain: %s", s->pid_file); ++ if (fd == -EPERM) { ++ log_unit_full(UNIT(s)->id, LOG_DEBUG, "Permission denied while opening PID file or potentially unsafe symlink chain, will now retry with relaxed checks: %s", s->pid_file); ++ ++ questionable_pid_file = true; ++ ++ fd = chase_symlinks(s->pid_file, NULL, CHASE_OPEN, NULL); ++ } + if (fd < 0) + return log_unit_full_errno(UNIT(s)->id, prio, fd, "Can't open PID file %s (yet?) after %s: %m", s->pid_file, service_state_to_string(s->state)); + +@@ -773,6 +779,11 @@ static int service_load_pid_file(Service *s, bool may_warn) { + if (r == 0) { + struct stat st; + ++ if (questionable_pid_file) { ++ log_unit_error(UNIT(s)->id, "Refusing to accept PID outside of service control group, acquired through unsafe symlink chain: %s", s->pid_file); ++ return -EPERM; ++ } ++ + /* Hmm, it's not clear if the new main PID is safe. Let's allow this if the PID file is owned by root */ + + if (fstat(fd, &st) < 0) diff --git a/SOURCES/0758-path-util-fix-more-path_is_mount-e792e890f-fallout.patch b/SOURCES/0758-path-util-fix-more-path_is_mount-e792e890f-fallout.patch new file mode 100644 index 0000000..6cfafb1 --- /dev/null +++ b/SOURCES/0758-path-util-fix-more-path_is_mount-e792e890f-fallout.patch @@ -0,0 +1,83 @@ +From a4f13a2fdf5cf1650edbb02ac0393c6815ef472c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 7 Apr 2015 16:03:45 +0200 +Subject: [PATCH] path-util: fix more path_is_mount e792e890f fallout + +(cherry picked from commit da00518b3f3a8b08d521c4b72068eafa2db566cc) + +Resolves: #1279231 +--- + src/core/automount.c | 6 ++---- + src/nspawn/nspawn.c | 2 +- + src/shared/cgroup-util.c | 6 ++++-- + src/test/test-path-util.c | 10 ++++++++-- + 4 files changed, 15 insertions(+), 9 deletions(-) + +diff --git a/src/core/automount.c b/src/core/automount.c +index 7b9c4aaf1d..2d6f5f3a77 100644 +--- a/src/core/automount.c ++++ b/src/core/automount.c +@@ -789,10 +789,8 @@ static int automount_start(Unit *u) { + assert(a); + assert(a->state == AUTOMOUNT_DEAD || a->state == AUTOMOUNT_FAILED); + +- if (path_is_mount_point(a->where, false)) { +- log_unit_error(u->id, +- "Path %s is already a mount point, refusing start for %s", +- a->where, u->id); ++ if (path_is_mount_point(a->where, false) > 0) { ++ log_unit_error(u->id, "Path %s is already a mount point, refusing start for %s", a->where, u->id); + return -EEXIST; + } + +diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c +index ee2e1832f1..e7ecee8674 100644 +--- a/src/nspawn/nspawn.c ++++ b/src/nspawn/nspawn.c +@@ -864,7 +864,7 @@ static int mount_all(const char *dest) { + return log_oom(); + + t = path_is_mount_point(where, true); +- if (t < 0) { ++ if (t < 0 && t != -ENOENT) { + log_error_errno(t, "Failed to detect whether %s is a mount point: %m", where); + + if (r == 0) +diff --git a/src/shared/cgroup-util.c b/src/shared/cgroup-util.c +index 4585450b39..f1bed8a25a 100644 +--- a/src/shared/cgroup-util.c ++++ b/src/shared/cgroup-util.c +@@ -489,8 +489,10 @@ int cg_get_path(const char *controller, const char *path, const char *suffix, ch + int r; + + r = path_is_mount_point("/sys/fs/cgroup", false); +- if (r <= 0) +- return r < 0 ? r : -ENOENT; ++ if (r < 0) ++ return r; ++ if (r == 0) ++ return -ENOENT; + + /* Cache this to save a few stat()s */ + good = true; +diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c +index aee1f4e036..aebfa3821d 100644 +--- a/src/test/test-path-util.c ++++ b/src/test/test-path-util.c +@@ -86,8 +86,14 @@ static void test_path(void) { + test_parent("/aa///file...", "/aa///"); + test_parent("file.../", NULL); + +- assert_se(path_is_mount_point("/", true)); +- assert_se(path_is_mount_point("/", false)); ++ assert_se(path_is_mount_point("/", true) > 0); ++ assert_se(path_is_mount_point("/", false) > 0); ++ ++ assert_se(path_is_mount_point("/proc", true) > 0); ++ assert_se(path_is_mount_point("/proc", false) > 0); ++ ++ assert_se(path_is_mount_point("/sys", true) > 0); ++ assert_se(path_is_mount_point("/sys", false) > 0); + + { + char p1[] = "aaa/bbb////ccc"; diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index 55e4fc7..df05cc8 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -7,7 +7,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 219 -Release: 67%{?dist} +Release: 67%{?dist}.1 # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: A System and Service Manager @@ -785,6 +785,18 @@ Patch0743: 0743-man-be-more-explicit-about-thread-safety-of-sd_journ.patch Patch0744: 0744-selinux-don-t-log-SELINUX_INFO-and-SELINUX_WARNING-m.patch Patch0745: 0745-fix-mis-merge.patch Patch0746: 0746-fs-util-chase_symlinks-prevent-double-free.patch +Patch0747: 0747-return-error-value-on-failure.patch +Patch0748: 0748-revert-local-changes-made-during-backport-of-the-tes.patch +Patch0749: 0749-core-timer-Prevent-timer-looping-when-unit-cannot-st.patch +Patch0750: 0750-core-add-a-Requires-dependency-between-units-and-the.patch +Patch0751: 0751-core-rerun-GC-logic-for-a-unit-that-loses-a-referenc.patch +Patch0752: 0752-pid1-rename-unit_check_gc-to-unit_may_gc.patch +Patch0753: 0753-pid1-include-the-source-unit-in-UnitRef.patch +Patch0754: 0754-pid1-fix-collection-of-cycles-of-units-which-referen.patch +Patch0755: 0755-pid1-free-basic-unit-information-at-the-very-end-bef.patch +Patch0756: 0756-pid1-properly-remove-references-to-the-unit-from-gc-.patch +Patch0757: 0757-service-relax-PID-file-symlink-chain-checks-a-bit-81.patch +Patch0758: 0758-path-util-fix-more-path_is_mount-e792e890f-fallout.patch %global num_patches %{lua: c=0; for i,p in ipairs(patches) do c=c+1; end; print(c);} @@ -1761,6 +1773,20 @@ fi %{_mandir}/man8/systemd-resolved.* %changelog +* Fri Jul 12 2019 Lukas Nykryn - 219-67.1 +- return error value on failure (#1729226) +- revert local changes made during backport of the test (#1729226) +- core/timer: Prevent timer looping when unit cannot start (#1729230) +- core: add a "Requires=" dependency between units and the slices they are located in (#1729228) +- core: rerun GC logic for a unit that loses a reference (#1729228) +- pid1: rename unit_check_gc to unit_may_gc (#1729228) +- pid1: include the source unit in UnitRef (#1729228) +- pid1: fix collection of cycles of units which reference one another (#1729228) +- pid1: free basic unit information at the very end, before freeing the unit (#1729228) +- pid1: properly remove references to the unit from gc queue during final cleanup (#1729228) +- service: relax PID file symlink chain checks a bit (#8133) (#1729414) +- path-util: fix more path_is_mount e792e890f fallout (#1279231) + * Wed Jun 19 2019 Michal Sekletár - 219-67 - fix mis-merge (#1714503) - fs-util: chase_symlinks(): prevent double fre (#1714782)