diff options
Diffstat (limited to 'src')
38 files changed, 443 insertions, 334 deletions
diff --git a/src/basic/meson.build b/src/basic/meson.build index 9a21457..b538775 100644 --- a/src/basic/meson.build +++ b/src/basic/meson.build @@ -274,7 +274,7 @@ filesystem_switch_case_h = custom_target( basic_sources += [filesystem_list_h, filesystem_switch_case_h, filesystems_gperf_h] -libbasic = static_library( +libbasic_static = static_library( 'basic', basic_sources, fundamental_sources, diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index dda5920..3a1b7b2 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -584,8 +584,9 @@ int vt_disallocate(const char *name) { (void) loop_write(fd2, "\033[r" /* clear scrolling region */ "\033[H" /* move home */ - "\033[3J", /* clear screen including scrollback, requires Linux 2.6.40 */ - 10); + "\033[3J" /* clear screen including scrollback, requires Linux 2.6.40 */ + "\033c", /* reset to initial state */ + SIZE_MAX); return 0; } @@ -1558,7 +1559,6 @@ int terminal_reset_ansi_seq(int fd) { return log_debug_errno(r, "Failed to set terminal to non-blocking mode: %m"); k = loop_write_full(fd, - "\033c" /* reset to initial state */ "\033[!p" /* soft terminal reset */ "\033]104\007" /* reset colors */ "\033[?7h", /* enable line-wrapping */ diff --git a/src/boot/efi/boot.c b/src/boot/efi/boot.c index 8287c21..e1f0817 100644 --- a/src/boot/efi/boot.c +++ b/src/boot/efi/boot.c @@ -1337,7 +1337,7 @@ static void boot_entry_parse_tries( return; /* Boot counter in the middle of the name? */ - if (!streq16(counter, suffix)) + if (!strcaseeq16(counter, suffix)) return; entry->tries_left = tries_left; 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/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/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/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/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/unit.c b/src/core/unit.c index 852926b..01c9983 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -129,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; } @@ -484,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; @@ -790,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); @@ -3816,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); @@ -3833,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) + if (u->load_state == UNIT_LOADED) { + _cleanup_strv_free_ char **dropins = NULL; + (void) unit_find_dropin_paths(u, &dropins); - 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)) + 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; } diff --git a/src/id128/id128.c b/src/id128/id128.c index fa86cf6..875d22d 100644 --- a/src/id128/id128.c +++ b/src/id128/id128.c @@ -16,7 +16,7 @@ #include "verbs.h" static Id128PrettyPrintMode arg_mode = ID128_PRINT_ID128; -static sd_id128_t arg_app = {}; +static sd_id128_t arg_app = SD_ID128_NULL; static bool arg_value = false; static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; @@ -72,15 +72,12 @@ static int verb_invocation_id(int argc, char **argv, void *userdata) { } static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first) { - sd_id128_t u; int r; assert(table); - if (sd_id128_is_null(arg_app)) - u = uuid; - else - assert_se(sd_id128_get_app_specific(uuid, arg_app, &u) == 0); + if (!name) + name = "XYZ"; if (arg_mode == ID128_PRINT_PRETTY) { _cleanup_free_ char *id = NULL; @@ -91,7 +88,7 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first ascii_strupper(id); - r = id128_pretty_print_sample(id, u); + r = id128_pretty_print_sample(id, uuid); if (r < 0) return r; if (!first) @@ -100,19 +97,19 @@ static int show_one(Table **table, const char *name, sd_id128_t uuid, bool first } if (arg_value) - return id128_pretty_print(u, arg_mode); + return id128_pretty_print(uuid, arg_mode); if (!*table) { *table = table_new("name", "id"); if (!*table) return log_oom(); + table_set_width(*table, 0); } return table_add_many(*table, TABLE_STRING, name, - arg_mode == ID128_PRINT_ID128 ? TABLE_ID128 : TABLE_UUID, - u); + arg_mode == ID128_PRINT_ID128 ? TABLE_ID128 : TABLE_UUID, uuid); } static int verb_show(int argc, char **argv, void *userdata) { @@ -120,23 +117,26 @@ static int verb_show(int argc, char **argv, void *userdata) { int r; argv = strv_skip(argv, 1); - if (strv_isempty(argv)) + if (strv_isempty(argv)) { + if (!sd_id128_is_null(arg_app)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "'show --app-specific=' can only be used with explicit UUID input."); + for (const GptPartitionType *e = gpt_partition_type_table; e->name; e++) { r = show_one(&table, e->name, e->uuid, e == gpt_partition_type_table); if (r < 0) return r; } - else + } else STRV_FOREACH(p, argv) { sd_id128_t uuid; - bool have_uuid; - const char *id; + const char *id = NULL; /* Check if the argument is an actual UUID first */ - have_uuid = sd_id128_from_string(*p, &uuid) >= 0; + bool is_uuid = sd_id128_from_string(*p, &uuid) >= 0; - if (have_uuid) - id = gpt_partition_type_uuid_to_string(uuid) ?: "XYZ"; + if (is_uuid) + id = gpt_partition_type_uuid_to_string(uuid); else { GptPartitionType type; @@ -148,6 +148,9 @@ static int verb_show(int argc, char **argv, void *userdata) { id = *p; } + if (!sd_id128_is_null(arg_app)) + assert_se(sd_id128_get_app_specific(uuid, arg_app, &uuid) >= 0); + r = show_one(&table, id, uuid, p == argv); if (r < 0) return r; diff --git a/src/kernel-install/90-loaderentry.install.in b/src/kernel-install/90-loaderentry.install.in index 766d321..4ef6aca 100755 --- a/src/kernel-install/90-loaderentry.install.in +++ b/src/kernel-install/90-loaderentry.install.in @@ -101,6 +101,11 @@ if [ -f "$TRIES_FILE" ]; then echo "$TRIES_FILE does not contain an integer." >&2 exit 1 fi + if [ -f "$LOADER_ENTRY" ]; then + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Removing previous loader entry '$LOADER_ENTRY' without boot counting." >&2 + rm -f "$LOADER_ENTRY" "${LOADER_ENTRY%.conf}+"*.conf + fi LOADER_ENTRY="${LOADER_ENTRY%.conf}+$TRIES.conf" fi diff --git a/src/kernel-install/90-uki-copy.install b/src/kernel-install/90-uki-copy.install index d443c4b..d6f7134 100755 --- a/src/kernel-install/90-uki-copy.install +++ b/src/kernel-install/90-uki-copy.install @@ -61,6 +61,12 @@ if [ -f "$TRIES_FILE" ]; then echo "$TRIES_FILE does not contain an integer." >&2 exit 1 fi + if [ -f "$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi" ]; then + [ "$KERNEL_INSTALL_VERBOSE" -gt 0 ] && \ + echo "Removing previous UKI '$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi' without boot counting." >&2 + rm -f "$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi" "$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION+"*.efi + fi + UKI_FILE="$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION+$TRIES.efi" else UKI_FILE="$UKI_DIR/$ENTRY_TOKEN-$KERNEL_VERSION.efi" diff --git a/src/libsystemd/meson.build b/src/libsystemd/meson.build index 6d4337d..2435492 100644 --- a/src/libsystemd/meson.build +++ b/src/libsystemd/meson.build @@ -118,7 +118,7 @@ libsystemd_static = static_library( libsystemd_sources, include_directories : libsystemd_includes, c_args : libsystemd_c_args, - link_with : [libbasic], + link_with : [libbasic_static], dependencies : [threads, librt, userspace], diff --git a/src/libsystemd/sd-device/device-enumerator.c b/src/libsystemd/sd-device/device-enumerator.c index 71ab3d8..00d3328 100644 --- a/src/libsystemd/sd-device/device-enumerator.c +++ b/src/libsystemd/sd-device/device-enumerator.c @@ -701,13 +701,11 @@ static int enumerator_scan_dir_and_add_devices( dir = opendir(path); if (!dir) { - bool ignore = errno == ENOENT; + /* This is necessarily racey, so ignore missing directories */ + if (errno == ENOENT) + return 0; - /* this is necessarily racey, so ignore missing directories */ - log_debug_errno(errno, - "sd-device-enumerator: Failed to open directory %s%s: %m", - path, ignore ? ", ignoring" : ""); - return ignore ? 0 : -errno; + return log_debug_errno(errno, "sd-device-enumerator: Failed to open directory '%s': %m", path); } FOREACH_DIRENT_ALL(de, dir, return -errno) { @@ -767,12 +765,10 @@ static int enumerator_scan_dir( dir = opendir(path); if (!dir) { - bool ignore = errno == ENOENT; + if (errno == ENOENT) + return 0; - log_debug_errno(errno, - "sd-device-enumerator: Failed to open directory %s%s: %m", - path, ignore ? ", ignoring" : ""); - return ignore ? 0 : -errno; + return log_debug_errno(errno, "sd-device-enumerator: Failed to open directory '%s': %m", path); } FOREACH_DIRENT_ALL(de, dir, return -errno) { @@ -804,12 +800,10 @@ static int enumerator_scan_devices_tag(sd_device_enumerator *enumerator, const c dir = opendir(path); if (!dir) { - bool ignore = errno == ENOENT; + if (errno == ENOENT) + return 0; - log_debug_errno(errno, - "sd-device-enumerator: Failed to open directory %s%s: %m", - path, ignore ? ", ignoring" : ""); - return ignore ? 0 : -errno; + return log_debug_errno(errno, "sd-device-enumerator: Failed to open directory '%s': %m", path); } /* TODO: filter away subsystems? */ @@ -892,12 +886,10 @@ static int parent_crawl_children(sd_device_enumerator *enumerator, const char *p dir = opendir(path); if (!dir) { - bool ignore = errno == ENOENT; + if (errno == ENOENT) + return 0; - log_debug_errno(errno, - "sd-device-enumerator: Failed to open directory %s%s: %m", - path, ignore ? ", ignoring" : ""); - return ignore ? 0 : -errno; + return log_debug_errno(errno, "sd-device-enumerator: Failed to open directory '%s': %m", path); } FOREACH_DIRENT_ALL(de, dir, return -errno) { diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index a657b6e..0521863 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -1484,8 +1484,11 @@ static int method_set_user_linger(sd_bus_message *message, void *userdata, sd_bu return -errno; u = hashmap_get(m->users, UID_TO_PTR(uid)); - if (u) + if (u) { + /* Make sure that disabling lingering will terminate the user tracking if no sessions pin it. */ + u->gc_mode = USER_GC_BY_PIN; user_add_to_gc_queue(u); + } } return sd_bus_reply_method_return(message, NULL); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 8066b3e..276d5b8 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -821,30 +821,30 @@ UserState user_get_state(User *u) { if (!u->started || u->runtime_dir_job) return USER_OPENING; - bool any = false, all_closing = true; + /* USER_GC_BY_PIN: Only pinning sessions count. None -> closing + * USER_GC_BY_ANY: 'manager' sessions also count. However, if lingering is enabled, 'lingering' state + * shall be preferred. 'online' if the manager is manually started by user. */ + + bool has_pinning = false, all_closing = true; LIST_FOREACH(sessions_by_user, i, u->sessions) { - SessionState state; + bool pinned = SESSION_CLASS_PIN_USER(i->class); - /* Ignore sessions that don't pin the user, i.e. are not supposed to have an effect on user state */ - if (!SESSION_CLASS_PIN_USER(i->class)) + if (u->gc_mode == USER_GC_BY_PIN && !pinned) continue; - state = session_get_state(i); - if (state == SESSION_ACTIVE) + has_pinning = has_pinning || pinned; + + SessionState state = session_get_state(i); + if (state == SESSION_ACTIVE && pinned) return USER_ACTIVE; if (state != SESSION_CLOSING) all_closing = false; - - any = true; } - if (any) - return all_closing ? USER_CLOSING : USER_ONLINE; - - if (user_check_linger_file(u) > 0 && user_unit_active(u)) + if (!has_pinning && user_check_linger_file(u) > 0 && user_unit_active(u)) return USER_LINGERING; - return USER_CLOSING; + return all_closing ? USER_CLOSING : USER_ONLINE; } int user_kill(User *u, int signo) { diff --git a/src/partition/meson.build b/src/partition/meson.build index 52e1368..2cfe43e 100644 --- a/src/partition/meson.build +++ b/src/partition/meson.build @@ -32,7 +32,7 @@ executables += [ 'sources' : files('repart.c'), 'c_args' : '-DSTANDALONE', 'link_with' : [ - libbasic, + libbasic_static, libshared_fdisk, libshared_static, libsystemd_static, diff --git a/src/partition/repart.c b/src/partition/repart.c index f87a87e..8a5ce7e 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -1895,6 +1895,34 @@ static int config_parse_encrypted_volume( static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_verity, verity_mode, VerityMode, VERITY_OFF, "Invalid verity mode"); static DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_minimize, minimize_mode, MinimizeMode, MINIMIZE_OFF, "Invalid minimize mode"); +static int partition_finalize_fstype(Partition *p, const char *path) { + _cleanup_free_ char *e = NULL, *upper = NULL; + + assert(p); + assert(path); + + if (!gpt_partition_type_has_filesystem(p->type)) + return 0; + + upper = strdup(partition_designator_to_string(p->type.designator)); + if (!upper) + return log_oom(); + + e = strjoin("SYSTEMD_REPART_OVERRIDE_FSTYPE_", string_replace_char(ascii_strupper(upper), '-', '_')); + if (!e) + return log_oom(); + + const char *v = secure_getenv(e); + if (!v || streq(p->format, v)) + return 0; + + log_syntax(NULL, LOG_NOTICE, path, 1, 0, + "Overriding defined file system type '%s' for '%s' partition with '%s'.", + p->format, partition_designator_to_string(p->type.designator), v); + + return free_and_strdup_warn(&p->format, v); +} + static int partition_read_definition(Partition *p, const char *path, const char *const *conf_file_dirs) { ConfigTableItem table[] = { @@ -2084,6 +2112,10 @@ static int partition_read_definition(Partition *p, const char *path, const char } else if (streq(p->split_name_format, "-")) p->split_name_format = mfree(p->split_name_format); + r = partition_finalize_fstype(p, path); + if (r < 0) + return r; + return 1; } diff --git a/src/shared/bootspec.c b/src/shared/bootspec.c index 4bc3ae7..9466866 100644 --- a/src/shared/bootspec.c +++ b/src/shared/bootspec.c @@ -505,6 +505,12 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { assert(a); assert(b); + /* This mimics a function of the same name in src/boot/efi/sd-boot.c */ + + r = CMP(a->tries_left == 0, b->tries_left == 0); + if (r != 0) + return r; + r = CMP(!a->sort_key, !b->sort_key); if (r != 0) return r; @@ -523,7 +529,18 @@ static int boot_entry_compare(const BootEntry *a, const BootEntry *b) { return r; } - return -strverscmp_improved(a->id, b->id); + r = -strverscmp_improved(a->id, b->id); + if (r != 0) + return r; + + if (a->tries_left != UINT_MAX || b->tries_left != UINT_MAX) + return 0; + + r = -CMP(a->tries_left, b->tries_left); + if (r != 0) + return r; + + return CMP(a->tries_done, b->tries_done); } static int config_check_inode_relevant_and_unseen(BootConfig *config, int fd, const char *fname) { @@ -743,11 +760,11 @@ static int find_sections( r = pe_load_headers(fd, &dos_header, &pe_header); if (r < 0) - return log_warning_errno(r, "Failed to parse PE file '%s': %m", path); + return log_error_errno(r, "Failed to parse PE file '%s': %m", path); r = pe_load_sections(fd, dos_header, pe_header, §ions); if (r < 0) - return log_warning_errno(r, "Failed to parse PE sections of '%s': %m", path); + return log_error_errno(r, "Failed to parse PE sections of '%s': %m", path); if (ret_pe_header) *ret_pe_header = TAKE_PTR(pe_header); @@ -809,7 +826,7 @@ static int find_osrel_section( r = pe_read_section_data(fd, pe_header, sections, ".osrel", PE_SECTION_SIZE_MAX, (void**) ret_osrelease, NULL); if (r < 0) - return log_warning_errno(r, "Failed to read .osrel section of '%s': %m", path); + return log_error_errno(r, "Failed to read .osrel section of '%s': %m", path); return 0; } @@ -829,7 +846,7 @@ static int find_uki_sections( return r; if (!pe_is_uki(pe_header, sections)) - return log_warning_errno(SYNTHETIC_ERRNO(EBADMSG), "Parsed PE file '%s' is not a UKI.", path); + return log_error_errno(SYNTHETIC_ERRNO(EBADMSG), "Parsed PE file '%s' is not a UKI.", path); r = find_osrel_section(fd, path, sections, pe_header, ret_osrelease); if (r < 0) diff --git a/src/shared/exec-util.c b/src/shared/exec-util.c index 996edbf..6f61eb2 100644 --- a/src/shared/exec-util.c +++ b/src/shared/exec-util.c @@ -609,5 +609,6 @@ int fork_agent(const char *name, const int except[], size_t n_except, pid_t *ret va_end(ap); execv(path, l); + log_error_errno(errno, "Failed to execute %s: %m", path); _exit(EXIT_FAILURE); } diff --git a/src/shared/gpt.c b/src/shared/gpt.c index d639463..f3e5247 100644 --- a/src/shared/gpt.c +++ b/src/shared/gpt.c @@ -143,21 +143,30 @@ const GptPartitionType gpt_partition_type_table[] = { _GPT_ARCH_SEXTET(ARM64, "aarch64"), /* Alias: must be listed after arm64 */ _GPT_ARCH_SEXTET(IA64, "ia64"), _GPT_ARCH_SEXTET(LOONGARCH64, "loongarch64"), + _GPT_ARCH_SEXTET(LOONGARCH64, "loong64"), /* Alias: must be listed after loongarch64 */ _GPT_ARCH_SEXTET(MIPS, "mips"), _GPT_ARCH_SEXTET(MIPS64, "mips64"), _GPT_ARCH_SEXTET(MIPS_LE, "mips-le"), + _GPT_ARCH_SEXTET(MIPS_LE, "mipsel"), /* Alias: must be listed after mips-le */ _GPT_ARCH_SEXTET(MIPS64_LE, "mips64-le"), + _GPT_ARCH_SEXTET(MIPS64_LE, "mips64el"), /* Alias: must be listed after mips64-le */ _GPT_ARCH_SEXTET(PARISC, "parisc"), + _GPT_ARCH_SEXTET(PARISC, "hppa"), /* Alias: must be listed after parisc */ _GPT_ARCH_SEXTET(PPC, "ppc"), _GPT_ARCH_SEXTET(PPC64, "ppc64"), _GPT_ARCH_SEXTET(PPC64_LE, "ppc64-le"), _GPT_ARCH_SEXTET(PPC64_LE, "ppc64le"), /* Alias: must be listed after ppc64-le */ + _GPT_ARCH_SEXTET(PPC64_LE, "ppc64el"), /* Alias: must be listed after ppc64-le */ _GPT_ARCH_SEXTET(RISCV32, "riscv32"), _GPT_ARCH_SEXTET(RISCV64, "riscv64"), _GPT_ARCH_SEXTET(S390, "s390"), _GPT_ARCH_SEXTET(S390X, "s390x"), _GPT_ARCH_SEXTET(TILEGX, "tilegx"), _GPT_ARCH_SEXTET(X86, "x86"), + _GPT_ARCH_SEXTET(X86, "i386"), /* Alias: must be listed after x86 */ + _GPT_ARCH_SEXTET(X86, "i486"), /* Alias: must be listed after x86 */ + _GPT_ARCH_SEXTET(X86, "i586"), /* Alias: must be listed after x86 */ + _GPT_ARCH_SEXTET(X86, "i686"), /* Alias: must be listed after x86 */ _GPT_ARCH_SEXTET(X86_64, "x86-64"), _GPT_ARCH_SEXTET(X86_64, "x86_64"), /* Alias: must be listed after x86-64 */ _GPT_ARCH_SEXTET(X86_64, "amd64"), /* Alias: must be listed after x86-64 */ @@ -339,6 +348,18 @@ bool gpt_partition_type_knows_no_auto(GptPartitionType type) { PARTITION_SWAP); } +bool gpt_partition_type_has_filesystem(GptPartitionType type) { + return IN_SET(type.designator, + PARTITION_ROOT, + PARTITION_USR, + PARTITION_HOME, + PARTITION_SRV, + PARTITION_ESP, + PARTITION_XBOOTLDR, + PARTITION_TMP, + PARTITION_VAR); +} + bool gpt_header_has_signature(const GptHeader *p) { assert(p); diff --git a/src/shared/gpt.h b/src/shared/gpt.h index 21976e5..3d04c19 100644 --- a/src/shared/gpt.h +++ b/src/shared/gpt.h @@ -72,6 +72,7 @@ const char *gpt_partition_type_mountpoint_nulstr(GptPartitionType type); bool gpt_partition_type_knows_read_only(GptPartitionType type); bool gpt_partition_type_knows_growfs(GptPartitionType type); bool gpt_partition_type_knows_no_auto(GptPartitionType type); +bool gpt_partition_type_has_filesystem(GptPartitionType type); typedef struct { uint8_t partition_type_guid[16]; diff --git a/src/shared/install.c b/src/shared/install.c index c94b456..53566b7 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -1989,7 +1989,9 @@ static int install_info_symlink_alias( } broken = r == 0; /* symlink target does not exist? */ - RET_GATHER(ret, create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes)); + r = create_symlink(lp, alias_target ?: info->path, alias_path, force || broken, changes, n_changes); + if (r != 0 && ret >= 0) + ret = r; } return ret; @@ -2012,7 +2014,7 @@ static int install_info_symlink_wants( UnitNameFlags valid_dst_type = UNIT_NAME_ANY; const char *n; - int r = 0, q; + int r, q; assert(info); assert(lp); @@ -2083,7 +2085,7 @@ static int install_info_symlink_wants( return -ENOMEM; q = create_symlink(lp, info->path, path, /* force = */ true, changes, n_changes); - if ((q < 0 && r >= 0) || r == 0) + if (q != 0 && r >= 0) r = q; if (unit_file_exists(scope, lp, dst) == 0) { @@ -2155,15 +2157,15 @@ static int install_info_apply( r = install_info_symlink_alias(scope, info, lp, config_path, force, changes, n_changes); q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->wanted_by, ".wants/", changes, n_changes); - if (r == 0) + if (q != 0 && r >= 0) r = q; q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->required_by, ".requires/", changes, n_changes); - if (r == 0) + if (q != 0 && r >= 0) r = q; q = install_info_symlink_wants(scope, file_flags, info, lp, config_path, info->upheld_by, ".upholds/", changes, n_changes); - if (r == 0) + if (q != 0 && r >= 0) r = q; return r; diff --git a/src/shared/meson.build b/src/shared/meson.build index c5106d8..e513c0e 100644 --- a/src/shared/meson.build +++ b/src/shared/meson.build @@ -358,7 +358,7 @@ libshared = shared_library( '-Wl,--version-script=' + libshared_sym_path], link_depends : libshared_sym_path, link_whole : [libshared_static, - libbasic, + libbasic_static, libsystemd_static], dependencies : [libshared_deps, userspace], diff --git a/src/shared/spawn-polkit-agent.c b/src/shared/spawn-polkit-agent.c index ce3c5fb..fd91bd6 100644 --- a/src/shared/spawn-polkit-agent.c +++ b/src/shared/spawn-polkit-agent.c @@ -43,16 +43,21 @@ int polkit_agent_open(void) { xsprintf(notify_fd, "%i", pipe_fd[1]); r = fork_agent("(polkit-agent)", - &pipe_fd[1], 1, + &pipe_fd[1], + 1, &agent_pid, POLKIT_AGENT_BINARY_PATH, - POLKIT_AGENT_BINARY_PATH, "--notify-fd", notify_fd, "--fallback", NULL); + POLKIT_AGENT_BINARY_PATH, + "--notify-fd", + notify_fd, + "--fallback", + NULL); /* Close the writing side, because that's the one for the agent */ safe_close(pipe_fd[1]); if (r < 0) - log_error_errno(r, "Failed to fork TTY ask password agent: %m"); + log_error_errno(r, "Failed to fork polkit agent: %m"); else /* Wait until the agent closes the fd */ (void) fd_wait_for_event(pipe_fd[0], POLLHUP, USEC_INFINITY); diff --git a/src/shared/varlink-internal.h b/src/shared/varlink-internal.h index 715202a..bc30108 100644 --- a/src/shared/varlink-internal.h +++ b/src/shared/varlink-internal.h @@ -6,5 +6,45 @@ #include "fdset.h" #include "varlink.h" +typedef struct VarlinkServerSocket VarlinkServerSocket; + +struct VarlinkServerSocket { + VarlinkServer *server; + + int fd; + char *address; + + sd_event_source *event_source; + + LIST_FIELDS(VarlinkServerSocket, sockets); +}; + +struct VarlinkServer { + unsigned n_ref; + VarlinkServerFlags flags; + + LIST_HEAD(VarlinkServerSocket, sockets); + + Hashmap *methods; /* Fully qualified symbol name of a method → VarlinkMethod */ + Hashmap *interfaces; /* Fully qualified interface name → VarlinkInterface* */ + Hashmap *symbols; /* Fully qualified symbol name of method/error → VarlinkSymbol* */ + VarlinkConnect connect_callback; + VarlinkDisconnect disconnect_callback; + + sd_event *event; + int64_t event_priority; + + unsigned n_connections; + Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */ + + void *userdata; + char *description; + + unsigned connections_max; + unsigned connections_per_uid_max; + + bool exit_on_idle; +}; + int varlink_server_serialize(VarlinkServer *s, FILE *f, FDSet *fds); int varlink_server_deserialize_one(VarlinkServer *s, const char *value, FDSet *fds); diff --git a/src/shared/varlink.c b/src/shared/varlink.c index 034e72b..0a6d2c8 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -210,46 +210,6 @@ struct Varlink { pid_t exec_pid; }; -typedef struct VarlinkServerSocket VarlinkServerSocket; - -struct VarlinkServerSocket { - VarlinkServer *server; - - int fd; - char *address; - - sd_event_source *event_source; - - LIST_FIELDS(VarlinkServerSocket, sockets); -}; - -struct VarlinkServer { - unsigned n_ref; - VarlinkServerFlags flags; - - LIST_HEAD(VarlinkServerSocket, sockets); - - Hashmap *methods; /* Fully qualified symbol name of a method → VarlinkMethod */ - Hashmap *interfaces; /* Fully qualified interface name → VarlinkInterface* */ - Hashmap *symbols; /* Fully qualified symbol name of method/error → VarlinkSymbol* */ - VarlinkConnect connect_callback; - VarlinkDisconnect disconnect_callback; - - sd_event *event; - int64_t event_priority; - - unsigned n_connections; - Hashmap *by_uid; /* UID_TO_PTR(uid) → UINT_TO_PTR(n_connections) */ - - void *userdata; - char *description; - - unsigned connections_max; - unsigned connections_per_uid_max; - - bool exit_on_idle; -}; - static const char* const varlink_state_table[_VARLINK_STATE_MAX] = { [VARLINK_IDLE_CLIENT] = "idle-client", [VARLINK_AWAITING_REPLY] = "awaiting-reply", diff --git a/src/shutdown/meson.build b/src/shutdown/meson.build index 219f9fd..9bc60f8 100644 --- a/src/shutdown/meson.build +++ b/src/shutdown/meson.build @@ -20,7 +20,7 @@ executables += [ 'sources' : systemd_shutdown_sources, 'c_args' : '-DSTANDALONE', 'link_with' : [ - libbasic, + libbasic_static, libshared_static, libsystemd_static, ], diff --git a/src/systemctl/systemctl-util.c b/src/systemctl/systemctl-util.c index 2482b7c..38e1f23 100644 --- a/src/systemctl/systemctl-util.c +++ b/src/systemctl/systemctl-util.c @@ -327,14 +327,15 @@ int get_active_triggering_units(sd_bus *bus, const char *unit, bool ignore_maske if (r < 0) return r; + if (unit_name_is_valid(name, UNIT_NAME_TEMPLATE)) + goto skip; + if (ignore_masked) { r = unit_is_masked(bus, name); if (r < 0) return r; - if (r > 0) { - *ret = NULL; - return 0; - } + if (r > 0) + goto skip; } dbus_path = unit_dbus_path_from_name(name); @@ -370,6 +371,10 @@ int get_active_triggering_units(sd_bus *bus, const char *unit, bool ignore_maske *ret = TAKE_PTR(active); return 0; + +skip: + *ret = NULL; + return 0; } void warn_triggering_units(sd_bus *bus, const char *unit, const char *operation, bool ignore_masked) { @@ -383,8 +388,8 @@ void warn_triggering_units(sd_bus *bus, const char *unit, const char *operation, r = get_active_triggering_units(bus, unit, ignore_masked, &triggered_by); if (r < 0) { - log_warning_errno(r, - "Failed to get triggering units for '%s', ignoring: %m", unit); + if (r != -ENOENT) /* A linked unit might have disappeared after disabling */ + log_warning_errno(r, "Failed to get triggering units for '%s', ignoring: %m", unit); return; } diff --git a/src/sysusers/meson.build b/src/sysusers/meson.build index 0f9c067..403d82a 100644 --- a/src/sysusers/meson.build +++ b/src/sysusers/meson.build @@ -14,7 +14,7 @@ executables += [ 'sources' : files('sysusers.c'), 'c_args' : '-DSTANDALONE', 'link_with' : [ - libbasic, + libbasic_static, libshared_static, libsystemd_static, ], diff --git a/src/test/meson.build b/src/test/meson.build index 3abbb94..9d3c7d6 100644 --- a/src/test/meson.build +++ b/src/test/meson.build @@ -274,7 +274,7 @@ executables += [ # only static linking apart from libdl, to make sure that the # module is linked to all libraries that it uses. 'sources' : files('test-dlopen.c'), - 'link_with' : libbasic, + 'link_with' : libbasic_static, 'dependencies' : libdl, 'install' : false, 'type' : 'manual', @@ -410,7 +410,7 @@ executables += [ }, test_template + { 'sources' : files('test-sizeof.c'), - 'link_with' : libbasic, + 'link_with' : libbasic_static, }, test_template + { 'sources' : files('test-time-util.c'), @@ -590,7 +590,7 @@ executables += [ test_template + { 'sources' : files('../libsystemd/sd-device/test-sd-device-thread.c'), 'link_with' : [ - libbasic, + libbasic_static, libsystemd, ], 'dependencies' : threads, @@ -598,7 +598,7 @@ executables += [ test_template + { 'sources' : files('../libudev/test-udev-device-thread.c'), 'link_with' : [ - libbasic, + libbasic_static, libudev, ], 'dependencies' : threads, diff --git a/src/test/test-install-root.c b/src/test/test-install-root.c index 1e7ed27..433cf22 100644 --- a/src/test/test-install-root.c +++ b/src/test/test-install-root.c @@ -23,12 +23,14 @@ TEST(basic_mask_and_enable) { InstallChange *changes = NULL; size_t n_changes = 0; - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "a.service", NULL) == -ENOENT); - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "b.service", NULL) == -ENOENT); - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "c.service", NULL) == -ENOENT); - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "d.service", NULL) == -ENOENT); - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "e.service", NULL) == -ENOENT); - assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "f.service", NULL) == -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "a.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "b.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "c.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "d.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "e.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "f.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "g.service", NULL), -ENOENT); + ASSERT_EQ(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "h.service", NULL), -ENOENT); p = strjoina(root, "/usr/lib/systemd/system/a.service"); assert_se(write_string_file(p, @@ -197,6 +199,24 @@ TEST(basic_mask_and_enable) { changes = NULL; n_changes = 0; assert_se(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "f.service", &state) >= 0 && state == UNIT_FILE_ENABLED); + + /* Test enabling units with only Alias= (unit_file_enable should return > 0 to indicate we did + * something, #33411) */ + + p = strjoina(root, SYSTEM_CONFIG_UNIT_DIR "/g.service"); + ASSERT_OK(write_string_file(p, + "[Install]\n" + "Alias=h.service\n", WRITE_STRING_FILE_CREATE)); + + ASSERT_GT(unit_file_enable(RUNTIME_SCOPE_SYSTEM, 0, root, STRV_MAKE("g.service"), &changes, &n_changes), 0); + install_changes_free(changes, n_changes); + changes = NULL; n_changes = 0; + + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "g.service", &state)); + ASSERT_EQ(state, UNIT_FILE_ENABLED); + + ASSERT_OK(unit_file_get_state(RUNTIME_SCOPE_SYSTEM, root, "h.service", &state)); + ASSERT_EQ(state, UNIT_FILE_ALIAS); } TEST(linked_units) { diff --git a/src/tmpfiles/meson.build b/src/tmpfiles/meson.build index 2e91850..09ad839 100644 --- a/src/tmpfiles/meson.build +++ b/src/tmpfiles/meson.build @@ -20,7 +20,7 @@ executables += [ 'sources' : systemd_tmpfiles_sources, 'c_args' : '-DSTANDALONE', 'link_with' : [ - libbasic, + libbasic_static, libshared_static, libsystemd_static, ], diff --git a/src/ukify/test/test_ukify.py b/src/ukify/test/test_ukify.py index 0e3f932..e3d49d4 100755 --- a/src/ukify/test/test_ukify.py +++ b/src/ukify/test/test_ukify.py @@ -1,11 +1,21 @@ #!/usr/bin/env python3 # SPDX-License-Identifier: LGPL-2.1-or-later +# The tests can be called via pytest: +# PATH=build/:$PATH pytest -v src/ukify/test/test_ukify.py +# or directly: +# PATH=build/:$PATH src/ukify/test/test_ukify.py +# or via the meson test machinery output: +# meson test -C build test-ukify -v +# or without verbose output: +# meson test -C build test-ukify + # pylint: disable=unused-import,import-outside-toplevel,useless-else-on-loop # pylint: disable=consider-using-with,wrong-import-position,unspecified-encoding # pylint: disable=protected-access,redefined-outer-name import base64 +import glob import json import os import pathlib @@ -389,28 +399,17 @@ def test_help_error(capsys): @pytest.fixture(scope='session') def kernel_initrd(): - opts = ukify.create_parser().parse_args(arg_tools) - bootctl = ukify.find_tool('bootctl', opts=opts) - if bootctl is None: - return None - - try: - text = subprocess.check_output([bootctl, 'list', '--json=short'], - text=True) - except subprocess.CalledProcessError: + items = sorted(glob.glob('/lib/modules/*/vmlinuz')) + if not items: return None - items = json.loads(text) + # This doesn't necessarilly give us the latest version, since we're just + # using alphanumeric ordering. But this is fine, a predictable result is + # enough. + linux = items[-1] - for item in items: - try: - linux = f"{item['root']}{item['linux']}" - initrd = f"{item['root']}{item['initrd'][0].split(' ')[0]}" - except (KeyError, IndexError): - continue - return ['--linux', linux, '--initrd', initrd] - else: - return None + # We don't look _into_ the initrd. Any file is OK. + return ['--linux', linux, '--initrd', ukify.__file__] def test_check_splash(): try: @@ -699,7 +698,7 @@ def test_pcr_signing(kernel_initrd, tmp_path): '--uname=1.2.3', '--cmdline=ARG1 ARG2 ARG3', '--os-release=ID=foobar\n', - '--pcr-banks=sha1', # use sha1 because it doesn't really matter + '--pcr-banks=sha384', # sha1 might not be allowed, use something else f'--pcr-private-key={priv.name}', ] + arg_tools @@ -742,8 +741,8 @@ def test_pcr_signing(kernel_initrd, tmp_path): assert open(tmp_path / 'out.cmdline').read() == 'ARG1 ARG2 ARG3' sig = open(tmp_path / 'out.pcrsig').read() sig = json.loads(sig) - assert list(sig.keys()) == ['sha1'] - assert len(sig['sha1']) == 4 # four items for four phases + assert list(sig.keys()) == ['sha384'] + assert len(sig['sha384']) == 4 # four items for four phases shutil.rmtree(tmp_path) @@ -775,7 +774,7 @@ def test_pcr_signing2(kernel_initrd, tmp_path): '--uname=1.2.3', '--cmdline=ARG1 ARG2 ARG3', '--os-release=ID=foobar\n', - '--pcr-banks=sha1', + '--pcr-banks=sha384', f'--pcrpkey={pub2.name}', f'--pcr-public-key={pub.name}', f'--pcr-private-key={priv.name}', @@ -815,8 +814,8 @@ def test_pcr_signing2(kernel_initrd, tmp_path): sig = open(tmp_path / 'out.pcrsig').read() sig = json.loads(sig) - assert list(sig.keys()) == ['sha1'] - assert len(sig['sha1']) == 6 # six items for six phases paths + assert list(sig.keys()) == ['sha384'] + assert len(sig['sha384']) == 6 # six items for six phases paths shutil.rmtree(tmp_path) diff --git a/src/vmspawn/vmspawn-util.h b/src/vmspawn/vmspawn-util.h index ee02752..959cb47 100644 --- a/src/vmspawn/vmspawn-util.h +++ b/src/vmspawn/vmspawn-util.h @@ -40,6 +40,8 @@ # define QEMU_MACHINE_TYPE "s390-ccw-virtio" #elif defined(__powerpc__) || defined(__powerpc64__) # define QEMU_MACHINE_TYPE "pseries" +#elif defined(__mips__) +# define QEMU_MACHINE_TYPE "malta" #else # error "No qemu machine defined for this architecture" #endif |