summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c212
-rw-r--r--src/core/cgroup.h16
-rw-r--r--src/core/core-varlink.c50
-rw-r--r--src/core/core-varlink.h2
-rw-r--r--src/core/dbus-execute.c4
-rw-r--r--src/core/dbus-manager.c4
-rw-r--r--src/core/exec-credential.c21
-rw-r--r--src/core/exec-invoke.c40
-rw-r--r--src/core/execute-serialize.c56
-rw-r--r--src/core/execute.c1
-rw-r--r--src/core/import-creds.c4
-rw-r--r--src/core/load-dropin.c2
-rw-r--r--src/core/load-dropin.h4
-rw-r--r--src/core/load-fragment.c7
-rw-r--r--src/core/manager-serialize.c2
-rw-r--r--src/core/manager.c70
-rw-r--r--src/core/meson.build32
-rw-r--r--src/core/namespace.c32
-rw-r--r--src/core/path.c2
-rw-r--r--src/core/service.c8
-rw-r--r--src/core/socket.c4
-rw-r--r--src/core/unit.c38
22 files changed, 325 insertions, 286 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 34fd2a2..76d7629 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -102,8 +102,9 @@ bool unit_has_startup_cgroup_constraints(Unit *u) {
c->startup_memory_low_set;
}
-bool unit_has_host_root_cgroup(Unit *u) {
+bool unit_has_host_root_cgroup(const Unit *u) {
assert(u);
+ assert(u->manager);
/* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
* the manager manages the root cgroup. */
@@ -2685,7 +2686,7 @@ int unit_set_cgroup_path(Unit *u, const char *path) {
if (crt && streq_ptr(crt->cgroup_path, path))
return 0;
- unit_release_cgroup(u);
+ unit_release_cgroup(u, /* drop_cgroup_runtime = */ true);
crt = unit_setup_cgroup_runtime(u);
if (!crt)
@@ -3483,7 +3484,7 @@ int unit_realize_cgroup(Unit *u) {
return unit_realize_cgroup_now(u, manager_state(u->manager));
}
-void unit_release_cgroup(Unit *u) {
+void unit_release_cgroup(Unit *u, bool drop_cgroup_runtime) {
assert(u);
/* Forgets all cgroup details for this cgroup — but does *not* destroy the cgroup. This is hence OK to call
@@ -3514,7 +3515,8 @@ void unit_release_cgroup(Unit *u) {
crt->cgroup_memory_inotify_wd = -1;
}
- *(CGroupRuntime**) ((uint8_t*) u + UNIT_VTABLE(u)->cgroup_runtime_offset) = cgroup_runtime_free(crt);
+ if (drop_cgroup_runtime)
+ *(CGroupRuntime**) ((uint8_t*) u + UNIT_VTABLE(u)->cgroup_runtime_offset) = cgroup_runtime_free(crt);
}
int unit_cgroup_is_empty(Unit *u) {
@@ -3535,22 +3537,24 @@ int unit_cgroup_is_empty(Unit *u) {
return r;
}
-bool unit_maybe_release_cgroup(Unit *u) {
+static bool unit_maybe_release_cgroup(Unit *u) {
int r;
- assert(u);
+ /* Releases the cgroup only if it is recursively empty.
+ * Returns true if the cgroup was released, false otherwise. */
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
- return true;
+ assert(u);
/* 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 = unit_cgroup_is_empty(u);
- if (r == 1) {
- unit_release_cgroup(u);
+ if (r > 0) {
+ /* Do not free CGroupRuntime when called from unit_prune_cgroup. Various accounting data
+ * we should keep, especially CPU usage and *_peak ones which would be shown even after
+ * the unit stops. */
+ unit_release_cgroup(u, /* drop_cgroup_runtime = */ false);
return true;
}
@@ -3558,8 +3562,8 @@ bool unit_maybe_release_cgroup(Unit *u) {
}
void unit_prune_cgroup(Unit *u) {
- int r;
bool is_root_slice;
+ int r;
assert(u);
@@ -3597,9 +3601,8 @@ void unit_prune_cgroup(Unit *u) {
if (!unit_maybe_release_cgroup(u)) /* Returns true if the cgroup was released */
return;
- crt = unit_get_cgroup_runtime(u); /* The above might have destroyed the runtime object, let's see if it's still there */
- if (!crt)
- return;
+ assert(crt == unit_get_cgroup_runtime(u));
+ assert(!crt->cgroup_path);
crt->cgroup_realized = false;
crt->cgroup_realized_mask = 0;
@@ -4526,6 +4529,10 @@ int unit_get_memory_accounting(Unit *u, CGroupMemoryAccountingMetric metric, uin
if (!UNIT_CGROUP_BOOL(u, memory_accounting))
return -ENODATA;
+ /* The root cgroup doesn't expose this information. */
+ if (unit_has_host_root_cgroup(u))
+ return -ENODATA;
+
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt)
return -ENODATA;
@@ -4533,10 +4540,6 @@ int unit_get_memory_accounting(Unit *u, CGroupMemoryAccountingMetric metric, uin
/* If the cgroup is already gone, we try to find the last cached value. */
goto finish;
- /* The root cgroup doesn't expose this information. */
- if (unit_has_host_root_cgroup(u))
- return -ENODATA;
-
if (!FLAGS_SET(crt->cgroup_realized_mask, CGROUP_MASK_MEMORY))
return -ENODATA;
@@ -4592,15 +4595,14 @@ int unit_get_tasks_current(Unit *u, uint64_t *ret) {
return cg_get_attribute_as_uint64("pids", crt->cgroup_path, "pids.current", ret);
}
-static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
- uint64_t ns;
+static int unit_get_cpu_usage_raw(const Unit *u, const CGroupRuntime *crt, nsec_t *ret) {
int r;
assert(u);
+ assert(crt);
assert(ret);
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!crt->cgroup_path)
return -ENODATA;
/* The root cgroup doesn't expose this information, let's get it from /proc instead */
@@ -4614,25 +4616,24 @@ static int unit_get_cpu_usage_raw(Unit *u, nsec_t *ret) {
r = cg_all_unified();
if (r < 0)
return r;
- if (r > 0) {
- _cleanup_free_ char *val = NULL;
- uint64_t us;
+ if (r == 0)
+ return cg_get_attribute_as_uint64("cpuacct", crt->cgroup_path, "cpuacct.usage", ret);
- r = cg_get_keyed_attribute("cpu", crt->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
- if (IN_SET(r, -ENOENT, -ENXIO))
- return -ENODATA;
- if (r < 0)
- return r;
+ _cleanup_free_ char *val = NULL;
+ uint64_t us;
- r = safe_atou64(val, &us);
- if (r < 0)
- return r;
+ r = cg_get_keyed_attribute("cpu", crt->cgroup_path, "cpu.stat", STRV_MAKE("usage_usec"), &val);
+ if (IN_SET(r, -ENOENT, -ENXIO))
+ return -ENODATA;
+ if (r < 0)
+ return r;
- ns = us * NSEC_PER_USEC;
- } else
- return cg_get_attribute_as_uint64("cpuacct", crt->cgroup_path, "cpuacct.usage", ret);
+ r = safe_atou64(val, &us);
+ if (r < 0)
+ return r;
+
+ *ret = us * NSEC_PER_USEC;
- *ret = ns;
return 0;
}
@@ -4646,14 +4647,14 @@ int unit_get_cpu_usage(Unit *u, nsec_t *ret) {
* started. If the cgroup has been removed already, returns the last cached value. To cache the value, simply
* call this function with a NULL return value. */
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
return -ENODATA;
- if (!UNIT_CGROUP_BOOL(u, cpu_accounting))
+ CGroupRuntime *crt = unit_get_cgroup_runtime(u);
+ if (!crt)
return -ENODATA;
- r = unit_get_cpu_usage_raw(u, &ns);
+ r = unit_get_cpu_usage_raw(u, crt, &ns);
if (r == -ENODATA && crt->cpu_usage_last != NSEC_INFINITY) {
/* If we can't get the CPU usage anymore (because the cgroup was already removed, for example), use our
* cached value. */
@@ -4694,7 +4695,7 @@ int unit_get_ip_accounting(
return -ENODATA;
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!crt)
return -ENODATA;
fd = IN_SET(metric, CGROUP_IP_INGRESS_BYTES, CGROUP_IP_INGRESS_PACKETS) ?
@@ -4770,22 +4771,27 @@ int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret) {
return 0;
}
-static int unit_get_io_accounting_raw(Unit *u, uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) {
- static const char *const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
+static int unit_get_io_accounting_raw(
+ const Unit *u,
+ const CGroupRuntime *crt,
+ uint64_t ret[static _CGROUP_IO_ACCOUNTING_METRIC_MAX]) {
+
+ static const char* const field_names[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {
[CGROUP_IO_READ_BYTES] = "rbytes=",
[CGROUP_IO_WRITE_BYTES] = "wbytes=",
[CGROUP_IO_READ_OPERATIONS] = "rios=",
[CGROUP_IO_WRITE_OPERATIONS] = "wios=",
};
+
uint64_t acc[_CGROUP_IO_ACCOUNTING_METRIC_MAX] = {};
_cleanup_free_ char *path = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
assert(u);
+ assert(crt);
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!crt->cgroup_path)
return -ENODATA;
if (unit_has_host_root_cgroup(u))
@@ -4869,13 +4875,13 @@ int unit_get_io_accounting(
return -ENODATA;
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!crt)
return -ENODATA;
if (allow_cache && crt->io_accounting_last[metric] != UINT64_MAX)
goto done;
- r = unit_get_io_accounting_raw(u, raw);
+ r = unit_get_io_accounting_raw(u, crt, raw);
if (r == -ENODATA && crt->io_accounting_last[metric] != UINT64_MAX)
goto done;
if (r < 0)
@@ -4896,45 +4902,52 @@ done:
return 0;
}
-int unit_reset_cpu_accounting(Unit *u) {
+static int unit_reset_cpu_accounting(Unit *unit, CGroupRuntime *crt) {
int r;
- assert(u);
-
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
- return 0;
+ assert(crt);
+ crt->cpu_usage_base = 0;
crt->cpu_usage_last = NSEC_INFINITY;
- r = unit_get_cpu_usage_raw(u, &crt->cpu_usage_base);
- if (r < 0) {
- crt->cpu_usage_base = 0;
- return r;
+ if (unit) {
+ r = unit_get_cpu_usage_raw(unit, crt, &crt->cpu_usage_base);
+ if (r < 0 && r != -ENODATA)
+ return r;
}
return 0;
}
-void unit_reset_memory_accounting_last(Unit *u) {
- assert(u);
+static int unit_reset_io_accounting(Unit *unit, CGroupRuntime *crt) {
+ int r;
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
- return;
+ assert(crt);
+
+ zero(crt->io_accounting_base);
+ FOREACH_ELEMENT(i, crt->io_accounting_last)
+ *i = UINT64_MAX;
+
+ if (unit) {
+ r = unit_get_io_accounting_raw(unit, crt, crt->io_accounting_base);
+ if (r < 0 && r != -ENODATA)
+ return r;
+ }
+
+ return 0;
+}
+
+static void cgroup_runtime_reset_memory_accounting_last(CGroupRuntime *crt) {
+ assert(crt);
FOREACH_ELEMENT(i, crt->memory_accounting_last)
*i = UINT64_MAX;
}
-int unit_reset_ip_accounting(Unit *u) {
+static int cgroup_runtime_reset_ip_accounting(CGroupRuntime *crt) {
int r = 0;
- assert(u);
-
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
- return 0;
+ assert(crt);
if (crt->ip_accounting_ingress_map_fd >= 0)
RET_GATHER(r, bpf_firewall_reset_accounting(crt->ip_accounting_ingress_map_fd));
@@ -4947,46 +4960,19 @@ int unit_reset_ip_accounting(Unit *u) {
return r;
}
-void unit_reset_io_accounting_last(Unit *u) {
- assert(u);
-
- CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
- return;
-
- FOREACH_ARRAY(i, crt->io_accounting_last, _CGROUP_IO_ACCOUNTING_METRIC_MAX)
- *i = UINT64_MAX;
-}
-
-int unit_reset_io_accounting(Unit *u) {
- int r;
+int unit_reset_accounting(Unit *u) {
+ int r = 0;
assert(u);
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
- if (!crt || !crt->cgroup_path)
+ if (!crt)
return 0;
- unit_reset_io_accounting_last(u);
-
- r = unit_get_io_accounting_raw(u, crt->io_accounting_base);
- if (r < 0) {
- zero(crt->io_accounting_base);
- return r;
- }
-
- return 0;
-}
-
-int unit_reset_accounting(Unit *u) {
- int r = 0;
-
- assert(u);
-
- RET_GATHER(r, unit_reset_cpu_accounting(u));
- RET_GATHER(r, unit_reset_io_accounting(u));
- RET_GATHER(r, unit_reset_ip_accounting(u));
- unit_reset_memory_accounting_last(u);
+ cgroup_runtime_reset_memory_accounting_last(crt);
+ RET_GATHER(r, unit_reset_cpu_accounting(u, crt));
+ RET_GATHER(r, unit_reset_io_accounting(u, crt));
+ RET_GATHER(r, cgroup_runtime_reset_ip_accounting(crt));
return r;
}
@@ -5210,7 +5196,7 @@ int unit_get_cpuset(Unit *u, CPUSet *cpus, const char *name) {
return parse_cpu_set_full(v, cpus, false, NULL, NULL, 0, NULL);
}
-CGroupRuntime *cgroup_runtime_new(void) {
+CGroupRuntime* cgroup_runtime_new(void) {
_cleanup_(cgroup_runtime_freep) CGroupRuntime *crt = NULL;
crt = new(CGroupRuntime, 1);
@@ -5218,8 +5204,6 @@ CGroupRuntime *cgroup_runtime_new(void) {
return NULL;
*crt = (CGroupRuntime) {
- .cpu_usage_last = NSEC_INFINITY,
-
.cgroup_control_inotify_wd = -1,
.cgroup_memory_inotify_wd = -1,
@@ -5234,19 +5218,15 @@ CGroupRuntime *cgroup_runtime_new(void) {
.cgroup_invalidated_mask = _CGROUP_MASK_ALL,
};
- FOREACH_ELEMENT(i, crt->memory_accounting_last)
- *i = UINT64_MAX;
- FOREACH_ELEMENT(i, crt->io_accounting_base)
- *i = UINT64_MAX;
- FOREACH_ELEMENT(i, crt->io_accounting_last)
- *i = UINT64_MAX;
- FOREACH_ELEMENT(i, crt->ip_accounting_extra)
- *i = UINT64_MAX;
+ unit_reset_cpu_accounting(/* unit = */ NULL, crt);
+ unit_reset_io_accounting(/* unit = */ NULL, crt);
+ cgroup_runtime_reset_memory_accounting_last(crt);
+ assert_se(cgroup_runtime_reset_ip_accounting(crt) >= 0);
return TAKE_PTR(crt);
}
-CGroupRuntime *cgroup_runtime_free(CGroupRuntime *crt) {
+CGroupRuntime* cgroup_runtime_free(CGroupRuntime *crt) {
if (!crt)
return NULL;
diff --git a/src/core/cgroup.h b/src/core/cgroup.h
index 72fe275..5170c7b 100644
--- a/src/core/cgroup.h
+++ b/src/core/cgroup.h
@@ -449,10 +449,7 @@ int unit_watch_cgroup_memory(Unit *u);
void unit_add_to_cgroup_realize_queue(Unit *u);
int unit_cgroup_is_empty(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_release_cgroup(Unit *u, bool drop_cgroup_runtime);
void unit_add_to_cgroup_empty_queue(Unit *u);
int unit_check_oomd_kill(Unit *u);
@@ -489,11 +486,6 @@ int unit_get_io_accounting(Unit *u, CGroupIOAccountingMetric metric, bool allow_
int unit_get_ip_accounting(Unit *u, CGroupIPAccountingMetric metric, uint64_t *ret);
int unit_get_effective_limit(Unit *u, CGroupLimitType type, uint64_t *ret);
-int unit_reset_cpu_accounting(Unit *u);
-void unit_reset_memory_accounting_last(Unit *u);
-int unit_reset_ip_accounting(Unit *u);
-void unit_reset_io_accounting_last(Unit *u);
-int unit_reset_io_accounting(Unit *u);
int unit_reset_accounting(Unit *u);
#define UNIT_CGROUP_BOOL(u, name) \
@@ -503,7 +495,7 @@ int unit_reset_accounting(Unit *u);
})
bool manager_owns_host_root_cgroup(Manager *m);
-bool unit_has_host_root_cgroup(Unit *u);
+bool unit_has_host_root_cgroup(const Unit *u);
bool unit_has_startup_cgroup_constraints(Unit *u);
@@ -527,8 +519,8 @@ int unit_cgroup_freezer_action(Unit *u, FreezerAction action);
const char* freezer_action_to_string(FreezerAction a) _const_;
FreezerAction freezer_action_from_string(const char *s) _pure_;
-CGroupRuntime *cgroup_runtime_new(void);
-CGroupRuntime *cgroup_runtime_free(CGroupRuntime *crt);
+CGroupRuntime* cgroup_runtime_new(void);
+CGroupRuntime* cgroup_runtime_free(CGroupRuntime *crt);
DEFINE_TRIVIAL_CLEANUP_FUNC(CGroupRuntime*, cgroup_runtime_free);
int cgroup_runtime_serialize(Unit *u, FILE *f, FDSet *fds);
diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c
index 3e6168d..8005f6d 100644
--- a/src/core/core-varlink.c
+++ b/src/core/core-varlink.c
@@ -5,6 +5,7 @@
#include "strv.h"
#include "user-util.h"
#include "varlink.h"
+#include "varlink-internal.h"
#include "varlink-io.systemd.UserDatabase.h"
#include "varlink-io.systemd.ManagedOOM.h"
@@ -500,12 +501,17 @@ static void vl_disconnect(VarlinkServer *s, Varlink *link, void *userdata) {
m->managed_oom_varlink = varlink_unref(link);
}
-static int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
+int manager_setup_varlink_server(Manager *m) {
_cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
assert(m);
- assert(ret);
+
+ if (m->varlink_server)
+ return 0;
+
+ if (!MANAGER_IS_SYSTEM(m))
+ return -EINVAL;
r = varlink_server_new(&s, VARLINK_SERVER_ACCOUNT_UID|VARLINK_SERVER_INHERIT_USERDATA);
if (r < 0)
@@ -533,51 +539,51 @@ static int manager_setup_varlink_server(Manager *m, VarlinkServer **ret) {
if (r < 0)
return log_debug_errno(r, "Failed to register varlink disconnect handler: %m");
- *ret = TAKE_PTR(s);
- return 0;
+ r = varlink_server_attach_event(s, m->event, EVENT_PRIORITY_IPC);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to attach varlink connection to event loop: %m");
+
+ m->varlink_server = TAKE_PTR(s);
+ return 1;
}
static int manager_varlink_init_system(Manager *m) {
- _cleanup_(varlink_server_unrefp) VarlinkServer *s = NULL;
int r;
assert(m);
- if (m->varlink_server)
- return 1;
-
if (!MANAGER_IS_SYSTEM(m))
return 0;
- r = manager_setup_varlink_server(m, &s);
+ r = manager_setup_varlink_server(m);
if (r < 0)
return log_error_errno(r, "Failed to set up varlink server: %m");
+ bool fresh = r > 0;
if (!MANAGER_IS_TEST_RUN(m)) {
(void) mkdir_p_label("/run/systemd/userdb", 0755);
FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) {
- if (MANAGER_IS_RELOADING(m)) {
- /* If manager is reloading, we skip listening on existing addresses, since
- * the fd should be acquired later through deserialization. */
- if (access(address, F_OK) >= 0)
+ if (!fresh) {
+ /* We might have got sockets through deserialization. Do not bind to them twice. */
+
+ bool found = false;
+ LIST_FOREACH(sockets, ss, m->varlink_server->sockets)
+ if (path_equal(ss->address, address)) {
+ found = true;
+ break;
+ }
+
+ if (found)
continue;
- if (errno != ENOENT)
- return log_error_errno(errno,
- "Failed to check if varlink socket '%s' exists: %m", address);
}
- r = varlink_server_listen_address(s, address, 0666);
+ r = varlink_server_listen_address(m->varlink_server, address, 0666);
if (r < 0)
return log_error_errno(r, "Failed to bind to varlink socket '%s': %m", address);
}
}
- r = varlink_server_attach_event(s, m->event, EVENT_PRIORITY_IPC);
- if (r < 0)
- return log_error_errno(r, "Failed to attach varlink connection to event loop: %m");
-
- m->varlink_server = TAKE_PTR(s);
return 1;
}
diff --git a/src/core/core-varlink.h b/src/core/core-varlink.h
index 20507a4..4b77620 100644
--- a/src/core/core-varlink.h
+++ b/src/core/core-varlink.h
@@ -3,6 +3,8 @@
#include "manager.h"
+int manager_setup_varlink_server(Manager *m);
+
int manager_varlink_init(Manager *m);
void manager_varlink_done(Manager *m);
diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c
index 21c260b..b0d9402 100644
--- a/src/core/dbus-execute.c
+++ b/src/core/dbus-execute.c
@@ -2743,10 +2743,6 @@ int bus_exec_context_set_transient_property(
if (!path_is_normalized(simplified))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
"WorkingDirectory= expects a normalized path or '~'");
-
- if (path_below_api_vfs(simplified))
- return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS,
- "WorkingDirectory= may not be below /proc/, /sys/ or /dev/");
}
}
diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c
index 2515f54..7da35a8 100644
--- a/src/core/dbus-manager.c
+++ b/src/core/dbus-manager.c
@@ -1708,6 +1708,10 @@ static int method_soft_reboot(sd_bus_message *message, void *userdata, sd_bus_er
assert(message);
+ if (!MANAGER_IS_SYSTEM(m))
+ return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED,
+ "Soft reboot is only supported by system manager.");
+
r = verify_run_space_permissive("soft reboot may fail", error);
if (r < 0)
return r;
diff --git a/src/core/exec-credential.c b/src/core/exec-credential.c
index f4cff57..6157ac4 100644
--- a/src/core/exec-credential.c
+++ b/src/core/exec-credential.c
@@ -353,6 +353,17 @@ static int load_credential_glob(
_cleanup_(erase_and_freep) char *data = NULL;
size_t size;
+ r = path_extract_filename(*p, &fn);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to extract filename from '%s': %m", *p);
+
+ if (faccessat(write_dfd, fn, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) {
+ log_debug("Skipping credential with duplicated ID %s at %s", fn, *p);
+ continue;
+ }
+ if (errno != ENOENT)
+ return log_debug_errno(errno, "Failed to test if credential %s exists: %m", fn);
+
/* path is absolute, hence pass AT_FDCWD as nop dir fd here */
r = read_full_file_full(
AT_FDCWD,
@@ -365,10 +376,6 @@ static int load_credential_glob(
if (r < 0)
return log_debug_errno(r, "Failed to read credential '%s': %m", *p);
- r = path_extract_filename(*p, &fn);
- if (r < 0)
- return log_debug_errno(r, "Failed to extract filename from '%s': %m", *p);
-
r = maybe_decrypt_and_write_credential(
write_dfd,
fn,
@@ -378,8 +385,6 @@ static int load_credential_glob(
ownership_ok,
data, size,
left);
- if (r == -EEXIST)
- continue;
if (r < 0)
return r;
}
@@ -717,8 +722,10 @@ static int acquire_credentials(
* EEXIST if the credential already exists. That's because the TPM2-based decryption is kinda
* slow and involved, hence it's nice to be able to skip that if the credential already
* exists anyway. */
- if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0)
+ if (faccessat(dfd, sc->id, F_OK, AT_SYMLINK_NOFOLLOW) >= 0) {
+ log_debug("Skipping credential with duplicated ID %s", sc->id);
continue;
+ }
if (errno != ENOENT)
return log_debug_errno(errno, "Failed to test if credential %s exists: %m", sc->id);
diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c
index ee8db04..5850a59 100644
--- a/src/core/exec-invoke.c
+++ b/src/core/exec-invoke.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include <linux/sched.h>
#include <sys/eventfd.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
@@ -44,6 +45,7 @@
#include "journal-send.h"
#include "missing_ioprio.h"
#include "missing_prctl.h"
+#include "missing_sched.h"
#include "missing_securebits.h"
#include "missing_syscall.h"
#include "mkdir-label.h"
@@ -1439,6 +1441,13 @@ static int apply_syscall_filter(const ExecContext *c, const ExecParameters *p, b
return r;
}
+ /* Sending over exec_fd or handoff_timestamp_fd requires write() syscall. */
+ if (p->exec_fd >= 0 || p->handoff_timestamp_fd >= 0) {
+ r = seccomp_filter_set_add_by_name(c->syscall_filter, c->syscall_allow_list, "write");
+ if (r < 0)
+ return r;
+ }
+
return seccomp_load_syscall_filter_set_raw(default_action, c->syscall_filter, action, false);
}
@@ -3775,7 +3784,7 @@ static int get_open_file_fd(const ExecContext *c, const ExecParameters *p, const
else if (FLAGS_SET(of->flags, OPENFILE_TRUNCATE))
flags |= O_TRUNC;
- fd = fd_reopen(ofd, flags | O_CLOEXEC);
+ fd = fd_reopen(ofd, flags|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return log_exec_error_errno(c, p, fd, "Failed to reopen file '%s': %m", of->path);
@@ -4011,7 +4020,7 @@ static int send_handoff_timestamp(
dual_timestamp dt;
dual_timestamp_now(&dt);
- if (send(p->handoff_timestamp_fd, (const usec_t[2]) { dt.realtime, dt.monotonic }, sizeof(usec_t) * 2, 0) < 0) {
+ if (write(p->handoff_timestamp_fd, (const usec_t[2]) { dt.realtime, dt.monotonic }, sizeof(usec_t) * 2) < 0) {
if (reterr_exit_status)
*reterr_exit_status = EXIT_EXEC;
return log_exec_error_errno(c, p, errno, "Failed to send handoff timestamp: %m");
@@ -4393,30 +4402,29 @@ int exec_invoke(
}
}
- if (context->nice_set) {
- r = setpriority_closest(context->nice);
- if (r < 0) {
- *exit_status = EXIT_NICE;
- return log_exec_error_errno(context, params, r, "Failed to set up process scheduling priority (nice level): %m");
- }
- }
-
if (context->cpu_sched_set) {
- struct sched_param param = {
+ struct sched_attr attr = {
+ .size = sizeof(attr),
+ .sched_policy = context->cpu_sched_policy,
.sched_priority = context->cpu_sched_priority,
+ .sched_flags = context->cpu_sched_reset_on_fork ? SCHED_FLAG_RESET_ON_FORK : 0,
};
- r = sched_setscheduler(0,
- context->cpu_sched_policy |
- (context->cpu_sched_reset_on_fork ?
- SCHED_RESET_ON_FORK : 0),
- &param);
+ r = sched_setattr(/* pid= */ 0, &attr, /* flags= */ 0);
if (r < 0) {
*exit_status = EXIT_SETSCHEDULER;
return log_exec_error_errno(context, params, errno, "Failed to set up CPU scheduling: %m");
}
}
+ if (context->nice_set) {
+ r = setpriority_closest(context->nice);
+ if (r < 0) {
+ *exit_status = EXIT_NICE;
+ return log_exec_error_errno(context, params, r, "Failed to set up process scheduling priority (nice level): %m");
+ }
+ }
+
if (context->cpu_affinity_from_numa || context->cpu_set.set) {
_cleanup_(cpu_set_reset) CPUSet converted_cpu_set = {};
const CPUSet *cpu_set;
diff --git a/src/core/execute-serialize.c b/src/core/execute-serialize.c
index ecd1e70..41b31e9 100644
--- a/src/core/execute-serialize.c
+++ b/src/core/execute-serialize.c
@@ -434,11 +434,11 @@ static int exec_cgroup_context_serialize(const CGroupContext *c, FILE *f) {
if (r < 0)
return r;
- r = serialize_strv(f, "exec-cgroup-context-ip-ingress-filter-path=", c->ip_filters_ingress);
+ r = serialize_strv(f, "exec-cgroup-context-ip-ingress-filter-path", c->ip_filters_ingress);
if (r < 0)
return r;
- r = serialize_strv(f, "exec-cgroup-context-ip-egress-filter-path=", c->ip_filters_egress);
+ r = serialize_strv(f, "exec-cgroup-context-ip-egress-filter-path", c->ip_filters_egress);
if (r < 0)
return r;
@@ -1759,15 +1759,23 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
if (r < 0)
return r;
- r = serialize_item(f, "exec-context-working-directory", c->working_directory);
+ r = serialize_item_escaped(f, "exec-context-working-directory", c->working_directory);
if (r < 0)
return r;
- r = serialize_item(f, "exec-context-root-directory", c->root_directory);
+ r = serialize_bool_elide(f, "exec-context-working-directory-missing-ok", c->working_directory_missing_ok);
if (r < 0)
return r;
- r = serialize_item(f, "exec-context-root-image", c->root_image);
+ r = serialize_bool_elide(f, "exec-context-working-directory-home", c->working_directory_home);
+ if (r < 0)
+ return r;
+
+ r = serialize_item_escaped(f, "exec-context-root-directory", c->root_directory);
+ if (r < 0)
+ return r;
+
+ r = serialize_item_escaped(f, "exec-context-root-image", c->root_image);
if (r < 0)
return r;
@@ -1982,14 +1990,6 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
return r;
}
- r = serialize_bool_elide(f, "exec-context-working-directory-missing-ok", c->working_directory_missing_ok);
- if (r < 0)
- return r;
-
- r = serialize_bool_elide(f, "exec-context-working-directory-home", c->working_directory_home);
- if (r < 0)
- return r;
-
if (c->oom_score_adjust_set) {
r = serialize_item_format(f, "exec-context-oom-score-adjust", "%i", c->oom_score_adjust);
if (r < 0)
@@ -2627,17 +2627,29 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
if (r < 0)
return r;
} else if ((val = startswith(l, "exec-context-working-directory="))) {
- r = free_and_strdup(&c->working_directory, val);
- if (r < 0)
- return r;
+ ssize_t k;
+ char *p;
+
+ k = cunescape(val, 0, &p);
+ if (k < 0)
+ return k;
+ free_and_replace(c->working_directory, p);
} else if ((val = startswith(l, "exec-context-root-directory="))) {
- r = free_and_strdup(&c->root_directory, val);
- if (r < 0)
- return r;
+ ssize_t k;
+ char *p;
+
+ k = cunescape(val, 0, &p);
+ if (k < 0)
+ return k;
+ free_and_replace(c->root_directory, p);
} else if ((val = startswith(l, "exec-context-root-image="))) {
- r = free_and_strdup(&c->root_image, val);
- if (r < 0)
- return r;
+ ssize_t k;
+ char *p;
+
+ k = cunescape(val, 0, &p);
+ if (k < 0)
+ return k;
+ free_and_replace(c->root_image, p);
} else if ((val = startswith(l, "exec-context-root-image-options="))) {
for (;;) {
_cleanup_free_ char *word = NULL, *mount_options = NULL, *partition = NULL;
diff --git a/src/core/execute.c b/src/core/execute.c
index 513e95e..f74665f 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -379,6 +379,7 @@ int exec_spawn(
assert(ret);
LOG_CONTEXT_PUSH_UNIT(unit);
+ LOG_CONTEXT_SET_LOG_LEVEL(context->log_level_max >= 0 ? context->log_level_max : log_get_max_level());
r = exec_context_load_environment(unit, context, &params->files_env);
if (r < 0)
diff --git a/src/core/import-creds.c b/src/core/import-creds.c
index f27ffed..e6cf40d 100644
--- a/src/core/import-creds.c
+++ b/src/core/import-creds.c
@@ -595,9 +595,11 @@ static int import_credentials_smbios(ImportCredentialContext *c) {
return log_oom();
r = read_virtual_file(p, sizeof(dmi_field_header) + CREDENTIALS_TOTAL_SIZE_MAX, (char**) &data, &size);
+ if (r == -ENOENT) /* Once we reach ENOENT there are no more DMI Type 11 fields around. */
+ break;
if (r < 0) {
/* Once we reach ENOENT there are no more DMI Type 11 fields around. */
- log_full_errno(r == -ENOENT ? LOG_DEBUG : LOG_WARNING, r, "Failed to open '%s', ignoring: %m", p);
+ log_warning_errno(r, "Failed to open '%s', ignoring: %m", p);
break;
}
diff --git a/src/core/load-dropin.c b/src/core/load-dropin.c
index fd45744..dc9c44e 100644
--- a/src/core/load-dropin.c
+++ b/src/core/load-dropin.c
@@ -102,7 +102,7 @@ int unit_load_dropin(Unit *u) {
return r;
/* Load .conf dropins */
- r = unit_find_dropin_paths(u, &l);
+ r = unit_find_dropin_paths(u, /* use_unit_path_cache = */ true, &l);
if (r <= 0)
return 0;
diff --git a/src/core/load-dropin.h b/src/core/load-dropin.h
index f0b87d3..141bc7d 100644
--- a/src/core/load-dropin.h
+++ b/src/core/load-dropin.h
@@ -6,12 +6,12 @@
/* Read service data supplementary drop-in directories */
-static inline int unit_find_dropin_paths(Unit *u, char ***paths) {
+static inline int unit_find_dropin_paths(Unit *u, bool use_unit_path_cache, char ***paths) {
assert(u);
return unit_file_find_dropin_paths(NULL,
u->manager->lookup_paths.search_path,
- u->manager->unit_path_cache,
+ use_unit_path_cache ? u->manager->unit_path_cache : NULL,
".d", ".conf",
u->id, u->aliases,
paths);
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index 5ae6888..a1a116a 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2634,7 +2634,8 @@ int config_parse_working_directory(
return missing_ok ? 0 : -ENOEXEC;
}
- r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS|(missing_ok ? 0 : PATH_CHECK_FATAL), unit, filename, line, lvalue);
+ r = path_simplify_and_warn(k, PATH_CHECK_ABSOLUTE|(missing_ok ? 0 : PATH_CHECK_FATAL),
+ unit, filename, line, lvalue);
if (r < 0)
return missing_ok ? 0 : -ENOEXEC;
@@ -5396,7 +5397,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(sresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS_DEV_OK, unit, filename, line, lvalue);
if (r < 0)
continue;
@@ -5412,7 +5413,7 @@ int config_parse_mount_images(
continue;
}
- r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS, unit, filename, line, lvalue);
+ r = path_simplify_and_warn(dresolved, PATH_CHECK_ABSOLUTE|PATH_CHECK_NON_API_VFS_DEV_OK, unit, filename, line, lvalue);
if (r < 0)
continue;
diff --git a/src/core/manager-serialize.c b/src/core/manager-serialize.c
index b4af82b..1d2959a 100644
--- a/src/core/manager-serialize.c
+++ b/src/core/manager-serialize.c
@@ -506,7 +506,7 @@ int manager_deserialize(Manager *m, FILE *f, FDSet *fds) {
return r;
} else if ((val = startswith(l, "varlink-server-socket-address="))) {
if (!m->varlink_server && MANAGER_IS_SYSTEM(m)) {
- r = manager_varlink_init(m);
+ r = manager_setup_varlink_server(m);
if (r < 0) {
log_warning_errno(r, "Failed to setup varlink server, ignoring: %m");
continue;
diff --git a/src/core/manager.c b/src/core/manager.c
index 90e72b0..5997ef0 100644
--- a/src/core/manager.c
+++ b/src/core/manager.c
@@ -3086,41 +3086,43 @@ static int manager_dispatch_signal_fd(sd_event_source *source, int fd, uint32_t
default: {
- /* Starting SIGRTMIN+0 */
- static const struct {
- const char *target;
- JobMode mode;
- } target_table[] = {
- [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
- [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
- [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
- [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
- [7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
- };
-
- /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
- static const ManagerObjective objective_table[] = {
- [0] = MANAGER_HALT,
- [1] = MANAGER_POWEROFF,
- [2] = MANAGER_REBOOT,
- [3] = MANAGER_KEXEC,
- [4] = MANAGER_SOFT_REBOOT,
- };
-
- if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
- (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
- int idx = (int) sfsi.ssi_signo - SIGRTMIN;
- manager_start_special(m, target_table[idx].target, target_table[idx].mode);
- break;
- }
+ if (MANAGER_IS_SYSTEM(m)) {
+ /* Starting SIGRTMIN+0 */
+ static const struct {
+ const char *target;
+ JobMode mode;
+ } target_table[] = {
+ [0] = { SPECIAL_DEFAULT_TARGET, JOB_ISOLATE },
+ [1] = { SPECIAL_RESCUE_TARGET, JOB_ISOLATE },
+ [2] = { SPECIAL_EMERGENCY_TARGET, JOB_ISOLATE },
+ [3] = { SPECIAL_HALT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [4] = { SPECIAL_POWEROFF_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [5] = { SPECIAL_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [6] = { SPECIAL_KEXEC_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ [7] = { SPECIAL_SOFT_REBOOT_TARGET, JOB_REPLACE_IRREVERSIBLY },
+ };
+
+ /* Starting SIGRTMIN+13, so that target halt and system halt are 10 apart */
+ static const ManagerObjective objective_table[] = {
+ [0] = MANAGER_HALT,
+ [1] = MANAGER_POWEROFF,
+ [2] = MANAGER_REBOOT,
+ [3] = MANAGER_KEXEC,
+ [4] = MANAGER_SOFT_REBOOT,
+ };
+
+ if ((int) sfsi.ssi_signo >= SIGRTMIN+0 &&
+ (int) sfsi.ssi_signo < SIGRTMIN+(int) ELEMENTSOF(target_table)) {
+ int idx = (int) sfsi.ssi_signo - SIGRTMIN;
+ manager_start_special(m, target_table[idx].target, target_table[idx].mode);
+ break;
+ }
- if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
- (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
- m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
- break;
+ if ((int) sfsi.ssi_signo >= SIGRTMIN+13 &&
+ (int) sfsi.ssi_signo < SIGRTMIN+13+(int) ELEMENTSOF(objective_table)) {
+ m->objective = objective_table[sfsi.ssi_signo - SIGRTMIN - 13];
+ break;
+ }
}
switch (sfsi.ssi_signo - SIGRTMIN) {
diff --git a/src/core/meson.build b/src/core/meson.build
index 7a2012a..dbeb752 100644
--- a/src/core/meson.build
+++ b/src/core/meson.build
@@ -110,17 +110,13 @@ load_fragment_gperf_nulstr_c = custom_target(
libcore_name = 'systemd-core-@0@'.format(shared_lib_tag)
-libcore = shared_library(
+libcore_static = static_library(
libcore_name,
libcore_sources,
load_fragment_gperf_c,
load_fragment_gperf_nulstr_c,
include_directories : includes,
c_args : ['-fvisibility=default'],
- link_args : ['-shared',
- '-Wl,--version-script=' + libshared_sym_path],
- link_depends : libshared_sym_path,
- link_with : libshared,
dependencies : [libacl,
libapparmor,
libaudit,
@@ -135,6 +131,16 @@ libcore = shared_library(
libselinux,
threads,
userspace],
+ build_by_default : false)
+
+libcore = shared_library(
+ libcore_name,
+ c_args : ['-fvisibility=default'],
+ link_args : ['-shared',
+ '-Wl,--version-script=' + libshared_sym_path],
+ link_depends : libshared_sym_path,
+ link_whole: libcore_static,
+ link_with : libshared,
install : true,
install_dir : pkglibdir)
@@ -150,6 +156,17 @@ systemd_executor_sources = files(
'exec-invoke.c',
)
+executor_libs = get_option('link-executor-shared') ? \
+ [
+ libcore,
+ libshared,
+ ] : [
+ libcore_static,
+ libshared_static,
+ libbasic_static,
+ libsystemd_static,
+ ]
+
executables += [
libexec_template + {
'name' : 'systemd',
@@ -167,10 +184,7 @@ executables += [
'public' : true,
'sources' : systemd_executor_sources,
'include_directories' : core_includes,
- 'link_with' : [
- libcore,
- libshared,
- ],
+ 'link_with' : executor_libs,
'dependencies' : [
libapparmor,
libpam,
diff --git a/src/core/namespace.c b/src/core/namespace.c
index 6c0dc94..b92bb01 100644
--- a/src/core/namespace.c
+++ b/src/core/namespace.c
@@ -1565,12 +1565,24 @@ static int apply_one_mount(
if (r < 0)
return log_debug_errno(r, "Failed to extract extension name from %s: %m", mount_entry_source(m));
- r = load_extension_release_pairs(mount_entry_source(m), IMAGE_SYSEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release);
+ r = load_extension_release_pairs(
+ mount_entry_source(m),
+ IMAGE_SYSEXT,
+ extension_name,
+ /* relax_extension_release_check= */ false,
+ &extension_release);
if (r == -ENOENT) {
- r = load_extension_release_pairs(mount_entry_source(m), IMAGE_CONFEXT, extension_name, /* relax_extension_release_check= */ false, &extension_release);
+ r = load_extension_release_pairs(
+ mount_entry_source(m),
+ IMAGE_CONFEXT,
+ extension_name,
+ /* relax_extension_release_check= */ false,
+ &extension_release);
if (r >= 0)
class = IMAGE_CONFEXT;
}
+ if (r == -ENOENT && m->ignore)
+ return 0;
if (r < 0)
return log_debug_errno(r, "Failed to acquire 'extension-release' data of extension tree %s: %m", mount_entry_source(m));
@@ -1585,12 +1597,6 @@ static int apply_one_mount(
if (isempty(host_os_release_id))
return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "'ID' field not found or empty in 'os-release' data of OS tree '%s'.", empty_to_root(root_directory));
- r = load_extension_release_pairs(mount_entry_source(m), class, extension_name, /* relax_extension_release_check= */ false, &extension_release);
- if (r == -ENOENT && m->ignore)
- return 0;
- if (r < 0)
- return log_debug_errno(r, "Failed to parse directory %s extension-release metadata: %m", extension_name);
-
r = extension_release_validate(
extension_name,
host_os_release_id,
@@ -1695,11 +1701,11 @@ static int apply_one_mount(
(void) mkdir_parents(mount_entry_path(m), 0755);
q = make_mount_point_inode_from_path(what, mount_entry_path(m), 0755);
- if (q < 0) {
- if (q != -EEXIST) // FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
- log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
- mount_entry_path(m));
- } else
+ if (q < 0 && q != -EEXIST)
+ // FIXME: this shouldn't be logged at LOG_WARNING, but be bubbled up, and logged there to avoid duplicate logging
+ log_warning_errno(q, "Failed to create destination mount point node '%s', ignoring: %m",
+ mount_entry_path(m));
+ else
try_again = true;
}
diff --git a/src/core/path.c b/src/core/path.c
index fdb6ca4..50f6db1 100644
--- a/src/core/path.c
+++ b/src/core/path.c
@@ -81,7 +81,7 @@ int path_spec_watch(PathSpec *s, sd_event_io_handler_t handler) {
tmp = *cut;
*cut = '\0';
- flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_ATTRIB | IN_CREATE | IN_MOVED_TO;
+ flags = IN_MOVE_SELF | IN_DELETE_SELF | IN_CREATE | IN_MOVED_TO;
} else {
cut = NULL;
flags = flags_table[s->type];
diff --git a/src/core/service.c b/src/core/service.c
index 8ec27c4..6e81460 100644
--- a/src/core/service.c
+++ b/src/core/service.c
@@ -1351,7 +1351,7 @@ static int service_coldplug(Unit *u) {
service_start_watchdog(s);
if (UNIT_ISSET(s->accept_socket)) {
- Socket* socket = SOCKET(UNIT_DEREF(s->accept_socket));
+ Socket *socket = SOCKET(UNIT_DEREF(s->accept_socket));
if (socket->max_connections_per_source > 0) {
SocketPeer *peer;
@@ -3220,8 +3220,8 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
} else if (streq(key, "accept-socket")) {
Unit *socket;
- if (u->type != UNIT_SOCKET) {
- log_unit_debug(u, "Failed to deserialize accept-socket: unit is not a socket");
+ if (unit_name_to_type(value) != UNIT_SOCKET) {
+ log_unit_debug(u, "Deserialized accept-socket is not a socket unit, ignoring: %s", value);
return 0;
}
@@ -3230,7 +3230,7 @@ static int service_deserialize_item(Unit *u, const char *key, const char *value,
log_unit_debug_errno(u, r, "Failed to load accept-socket unit '%s': %m", value);
else {
unit_ref_set(&s->accept_socket, u, socket);
- SOCKET(socket)->n_connections++;
+ ASSERT_PTR(SOCKET(socket))->n_connections++;
}
} else if (streq(key, "socket-fd")) {
diff --git a/src/core/socket.c b/src/core/socket.c
index 41147d4..0694fe7 100644
--- a/src/core/socket.c
+++ b/src/core/socket.c
@@ -2481,7 +2481,7 @@ static int socket_start(Unit *u) {
/* If the service is already active we cannot start the
* socket */
if (!IN_SET(service->state,
- SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
+ SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_DEAD_RESOURCES_PINNED, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED))
return log_unit_error_errno(u, SYNTHETIC_ERRNO(EBUSY),
"Socket service %s already active, refusing.", UNIT(service)->id);
@@ -3369,7 +3369,7 @@ static void socket_trigger_notify(Unit *u, Unit *other) {
return;
if (IN_SET(SERVICE(other)->state,
- SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
+ SERVICE_DEAD, SERVICE_DEAD_BEFORE_AUTO_RESTART, SERVICE_DEAD_RESOURCES_PINNED, SERVICE_FAILED, SERVICE_FAILED_BEFORE_AUTO_RESTART,
SERVICE_FINAL_SIGTERM, SERVICE_FINAL_SIGKILL,
SERVICE_AUTO_RESTART, SERVICE_AUTO_RESTART_QUEUED))
socket_enter_listening(s);
diff --git a/src/core/unit.c b/src/core/unit.c
index 2d40618..4ca7dc4 100644
--- a/src/core/unit.c
+++ b/src/core/unit.c
@@ -41,6 +41,7 @@
#include "logarithm.h"
#include "macro.h"
#include "mkdir-label.h"
+#include "mountpoint-util.h"
#include "path-util.h"
#include "process-util.h"
#include "rm-rf.h"
@@ -128,9 +129,6 @@ Unit* unit_new(Manager *m, size_t size) {
.burst = 16
};
- unit_reset_memory_accounting_last(u);
- unit_reset_io_accounting_last(u);
-
return u;
}
@@ -483,8 +481,8 @@ bool unit_may_gc(Unit *u) {
/* If the unit has a cgroup, then check whether there's anything in it. If so, we should stay
* around. Units with active processes should never be collected. */
r = unit_cgroup_is_empty(u);
- if (r <= 0 && r != -ENXIO)
- return false; /* ENXIO means: currently not realized */
+ if (r <= 0 && !IN_SET(r, -ENXIO, -EOWNERDEAD))
+ return false; /* ENXIO/EOWNERDEAD means: currently not realized */
if (!UNIT_VTABLE(u)->may_gc)
return true;
@@ -789,7 +787,7 @@ Unit* unit_free(Unit *u) {
if (u->on_console)
manager_unref_console(u->manager);
- unit_release_cgroup(u);
+ unit_release_cgroup(u, /* drop_cgroup_runtime = */ true);
if (!MANAGER_IS_RELOADING(u->manager))
unit_unlink_state_files(u);
@@ -1405,11 +1403,13 @@ int unit_load_fragment_and_dropin(Unit *u, bool fragment_required) {
u->load_state = UNIT_LOADED;
}
+ u = unit_follow_merge(u);
+
/* Load drop-in directory data. If u is an alias, we might be reloading the
* target unit needlessly. But we cannot be sure which drops-ins have already
* been loaded and which not, at least without doing complicated book-keeping,
* so let's always reread all drop-ins. */
- r = unit_load_dropin(unit_follow_merge(u));
+ r = unit_load_dropin(u);
if (r < 0)
return r;
@@ -3813,8 +3813,6 @@ static bool fragment_mtime_newer(const char *path, usec_t mtime, bool path_maske
}
bool unit_need_daemon_reload(Unit *u) {
- _cleanup_strv_free_ char **dropins = NULL;
-
assert(u);
assert(u->manager);
@@ -3830,16 +3828,20 @@ bool unit_need_daemon_reload(Unit *u) {
if (fragment_mtime_newer(u->source_path, u->source_mtime, false))
return true;
- if (u->load_state == UNIT_LOADED)
- (void) unit_find_dropin_paths(u, &dropins);
- if (!strv_equal(u->dropin_paths, dropins))
- return true;
+ if (u->load_state == UNIT_LOADED) {
+ _cleanup_strv_free_ char **dropins = NULL;
+
+ (void) unit_find_dropin_paths(u, /* use_unit_path_cache = */ false, &dropins);
- /* … any drop-ins that are masked are simply omitted from the list. */
- STRV_FOREACH(path, u->dropin_paths)
- if (fragment_mtime_newer(*path, u->dropin_mtime, false))
+ if (!strv_equal(u->dropin_paths, dropins))
return true;
+ /* … any drop-ins that are masked are simply omitted from the list. */
+ STRV_FOREACH(path, u->dropin_paths)
+ if (fragment_mtime_newer(*path, u->dropin_mtime, false))
+ return true;
+ }
+
return false;
}
@@ -4234,6 +4236,10 @@ static int unit_verify_contexts(const Unit *u, const ExecContext *ec) {
if (ec->dynamic_user && ec->working_directory_home)
return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "WorkingDirectory=~ is not allowed under DynamicUser=yes. Refusing.");
+ if (ec->working_directory && path_below_api_vfs(ec->working_directory) &&
+ exec_needs_mount_namespace(ec, /* params = */ NULL, /* runtime = */ NULL))
+ return log_unit_error_errno(u, SYNTHETIC_ERRNO(ENOEXEC), "WorkingDirectory= may not be below /proc/, /sys/ or /dev/ when using mount namespacing. Refusing.");
+
return 0;
}