1
0
mirror of https://github.com/systemd/systemd.git synced 2025-02-25 21:57:32 +03:00

core/unit: search shared namespace in transitive relation of JoinsNamespaceOf=

Previously, dependency chain of JoinsNamespaceOf= did not work, e.g.
- a.service has JoinsNamespaceOf=b.service
- b.service has JoinsNamespaceOf=c.service
if, first c.service, next a.service, finally b.service is started,
then a.service is not joined to the namespace of c.service. And, as
mentioned in the document, the namespace used by b.service is not
deterministic.

This makes when searching exsiting namespace to be joined, all units in
the transitive dependency of JoinsNamespaceOf= are checked.
This commit is contained in:
Yu Watanabe 2023-05-25 18:08:37 +09:00
parent a60f96fcf5
commit 83123a4498
5 changed files with 39 additions and 6 deletions

View File

@ -4888,6 +4888,7 @@ int unit_require_mounts_for(Unit *u, const char *path, UnitDependencyMask mask)
int unit_setup_exec_runtime(Unit *u) {
_cleanup_(exec_shared_runtime_unrefp) ExecSharedRuntime *esr = NULL;
_cleanup_(dynamic_creds_unrefp) DynamicCreds *dcreds = NULL;
_cleanup_set_free_ Set *units = NULL;
ExecRuntime **rt;
ExecContext *ec;
size_t offset;
@ -4905,8 +4906,12 @@ int unit_setup_exec_runtime(Unit *u) {
ec = unit_get_exec_context(u);
assert(ec);
r = unit_get_transitive_dependency_set(u, UNIT_ATOM_JOINS_NAMESPACE_OF, &units);
if (r < 0)
return r;
/* Try to get it from somebody else */
UNIT_FOREACH_DEPENDENCY(other, u, UNIT_ATOM_JOINS_NAMESPACE_OF) {
SET_FOREACH(other, units) {
r = exec_shared_runtime_acquire(u->manager, NULL, other->id, false, &esr);
if (r < 0)
return r;
@ -6111,6 +6116,33 @@ int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***re
return (int) n;
}
int unit_get_transitive_dependency_set(Unit *u, UnitDependencyAtom atom, Set **ret) {
_cleanup_set_free_ Set *units = NULL, *queue = NULL;
Unit *other;
int r;
assert(u);
assert(ret);
/* Similar to unit_get_dependency_array(), but also search the same dependency in other units. */
do {
UNIT_FOREACH_DEPENDENCY(other, u, atom) {
r = set_ensure_put(&units, NULL, other);
if (r < 0)
return r;
if (r == 0)
continue;
r = set_ensure_put(&queue, NULL, other);
if (r < 0)
return r;
}
} while ((u = set_steal_first(queue)));
*ret = TAKE_PTR(units);
return 0;
}
const ActivationDetailsVTable * const activation_details_vtable[_UNIT_TYPE_MAX] = {
[UNIT_PATH] = &activation_details_path_vtable,
[UNIT_TIMER] = &activation_details_timer_vtable,

View File

@ -810,6 +810,7 @@ static inline const UnitVTable* UNIT_VTABLE(const Unit *u) {
Unit* unit_has_dependency(const Unit *u, UnitDependencyAtom atom, Unit *other);
int unit_get_dependency_array(const Unit *u, UnitDependencyAtom atom, Unit ***ret_array);
int unit_get_transitive_dependency_set(Unit *u, UnitDependencyAtom atom, Set **ret);
static inline Hashmap* unit_get_dependencies(Unit *u, UnitDependency d) {
return hashmap_get(u->dependencies, UNIT_DEPENDENCY_TO_PTR(d));

View File

@ -6,6 +6,6 @@ JoinsNamespaceOf=testsuite-23-joins-namespace-of-8.service
Type=oneshot
MountAPIVFS=yes
PrivateTmp=yes
ExecStart=test ! -e /tmp/shared-private-file-x
ExecStart=test -e /tmp/shared-private-file-x
ExecStart=test ! -e /tmp/shared-private-file-y
ExecStart=touch /tmp/hoge

View File

@ -5,5 +5,5 @@ NotifyAccess=all
MountAPIVFS=yes
PrivateTmp=yes
ExecStartPre=test -e /tmp/shared-private-file-x
ExecStartPre=test ! -e /tmp/hoge
ExecStartPre=test -e /tmp/hoge
ExecStart=/bin/bash -c 'touch /tmp/shared-private-file-y && systemd-notify --ready && sleep infinity'

View File

@ -6,6 +6,6 @@ JoinsNamespaceOf=testsuite-23-joins-namespace-of-8.service
Type=oneshot
MountAPIVFS=yes
PrivateTmp=yes
ExecStart=test ! -e /tmp/shared-private-file-x
ExecStart=test ! -e /tmp/shared-private-file-y
ExecStart=test ! -e /tmp/hoge
ExecStart=test -e /tmp/shared-private-file-x
ExecStart=test -e /tmp/shared-private-file-y
ExecStart=test -e /tmp/hoge