diff --git a/meson.build b/meson.build index f03032aa2e..f953eeab13 100644 --- a/meson.build +++ b/meson.build @@ -78,6 +78,9 @@ conf.set10('FUZZ_USE_SIZE_LIMIT', fuzzer_build) # We'll set this to '1' for EFI builds in a different place. conf.set10('SD_BOOT', false) +link_executor_shared = get_option('link-executor-shared') +conf.set10('BUILD_EXECUTOR_SINGLE', link_executor_shared == 'single') + # Create a title-less summary section early, so it ends up first in the output. # More items are added later after they have been detected. summary({ diff --git a/meson_options.txt b/meson_options.txt index b2fddf8a34..701272d13a 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -15,8 +15,8 @@ option('split-bin', type : 'combo', choices : ['auto', 'true', 'false'], description : 'sbin is not a symlink to bin') option('link-udev-shared', type : 'boolean', description : 'link systemd-udevd and its helpers to libsystemd-shared.so') -option('link-executor-shared', type : 'boolean', - description : 'link systemd-executor to libsystemd-shared.so and libsystemd-core.so') +option('link-executor-shared', type : 'combo', choices : ['true', 'false', 'single'], + description : 'link systemd-executor to libsystemd-shared.so and libsystemd-core.so, or into systemd') option('link-systemctl-shared', type: 'boolean', description : 'link systemctl against libsystemd-shared.so') option('link-networkd-shared', type: 'boolean', diff --git a/src/core/execute.c b/src/core/execute.c index 4a95473e46..c2e8bc82b7 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -479,7 +479,6 @@ int exec_spawn( assert(unit); assert(unit->manager); assert(unit->manager->executor_fd >= 0); - assert(unit->manager->executor_path); assert(command); assert(context); assert(params); @@ -580,7 +579,7 @@ int exec_spawn( /* The executor binary is pinned, to avoid compatibility problems during upgrades. */ r = posix_spawn_wrapper( FORMAT_PROC_FD_PATH(unit->manager->executor_fd), - STRV_MAKE(unit->manager->executor_path, + STRV_MAKE("systemd-executor", "--deserialize", serialization_fd_number, "--log-level", max_log_levels, "--log-target", log_target_to_string(manager_get_executor_log_target(unit->manager))), diff --git a/src/core/executor.c b/src/core/executor.c index 00761c6e3f..b227584789 100644 --- a/src/core/executor.c +++ b/src/core/executor.c @@ -13,6 +13,7 @@ #include "exec-invoke.h" #include "execute.h" #include "execute-serialize.h" +#include "executor.h" #include "exit-status.h" #include "fd-util.h" #include "fdset.h" @@ -38,7 +39,7 @@ static int help(void) { if (r < 0) return log_oom(); - r = option_parser_get_help_table(&options); + r = option_parser_get_help_table_ns("systemd-executor", &options); if (r < 0) return r; @@ -62,11 +63,13 @@ static int parse_argv(int argc, char *argv[]) { assert(argc >= 0); assert(argv); - OptionParser opts = { argc, argv }; + OptionParser opts = { argc, argv, .namespace = "systemd-executor" }; FOREACH_OPTION_OR_RETURN(c, &opts) switch (c) { + OPTION_NAMESPACE("systemd-executor"): {} + OPTION_COMMON_HELP: return help(); @@ -226,7 +229,7 @@ static int run(int argc, char *argv[]) { return exit_status; } -int main(int argc, char *argv[]) { +int run_executor(int argc, char *argv[]) { int r; /* We use safe_fork() for spawning sd-pam helper process, which internally calls rename_process(). @@ -241,3 +244,7 @@ int main(int argc, char *argv[]) { return r < 0 ? EXIT_FAILURE : r; } + +#if !BUILD_EXECUTOR_SINGLE +_alias_(run_executor) main; +#endif diff --git a/src/core/executor.h b/src/core/executor.h new file mode 100644 index 0000000000..75d2abe0e5 --- /dev/null +++ b/src/core/executor.h @@ -0,0 +1,3 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ + +int run_executor(int argc, char *argv[]); diff --git a/src/core/main.c b/src/core/main.c index de0916476f..6c83953f30 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -45,6 +45,7 @@ #include "emergency-action.h" #include "env-util.h" #include "escape.h" +#include "executor.h" #include "extract-word.h" #include "fd-util.h" #include "fdset.h" @@ -1038,13 +1039,19 @@ static int parse_argv(int argc, char *argv[]) { assert(argv); int log_level_shift = getpid_cached() == 1 ? LOG_DEBUG - LOG_ERR : 0; - OptionParser opts = { argc, argv, .log_level_shift = log_level_shift }; + OptionParser opts = { + argc, argv, + .namespace = "systemd", + .log_level_shift = log_level_shift, + }; /* Note: when new options are added here, also add them to the exclusion list in proc-cmdline.c! */ FOREACH_OPTION(c, &opts) switch (c) { + OPTION_NAMESPACE("systemd"): {} + OPTION_COMMON_HELP: arg_action = ACTION_HELP; break; @@ -1279,7 +1286,7 @@ static int help(void) { _cleanup_(table_unrefp) Table *options = NULL; int r; - r = option_parser_get_help_table(&options); + r = option_parser_get_help_table_ns("systemd", &options); if (r < 0) return r; @@ -3430,7 +3437,7 @@ static int save_env(void) { return 0; } -int main(int argc, char *argv[]) { +static int run_systemd(int argc, char *argv[]) { dual_timestamp initrd_timestamp = DUAL_TIMESTAMP_NULL, userspace_timestamp = DUAL_TIMESTAMP_NULL, @@ -3911,3 +3918,11 @@ finish: reset_arguments(); return retval; } + +int main(int argc, char *argv[]) { +#if BUILD_EXECUTOR_SINGLE + if (invoked_as(argv, "executor")) + return run_executor(argc, argv); +#endif + return run_systemd(argc, argv); +} diff --git a/src/core/manager.c b/src/core/manager.c index 1ee2228c89..d89b1eae0d 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -895,6 +895,30 @@ usec_t manager_default_timeout(RuntimeScope scope) { return scope == RUNTIME_SCOPE_SYSTEM ? DEFAULT_TIMEOUT_USEC : DEFAULT_USER_TIMEOUT_USEC; } +static int pin_executor_binary(int *ret_fd) { + _cleanup_free_ char *path = NULL; + + assert(ret_fd); + +#if BUILD_EXECUTOR_SINGLE + int r; + + r = open_and_check_executable("/proc/self/exe", /* root= */ NULL, &path, ret_fd); + if (r < 0) + return log_debug_errno(r, "Failed to pin executor binary %s: %m", "/proc/self/exe"); +#else + int fd; + + fd = pin_callout_binary(SYSTEMD_EXECUTOR_BINARY_PATH, &path); + if (fd < 0) + return log_debug_errno(fd, "Failed to pin executor binary %s: %m", SYSTEMD_EXECUTOR_BINARY_PATH); + *ret_fd = fd; +#endif + + log_debug("Using systemd-executor binary %s.", path); + return 0; +} + int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags, Manager **ret) { _cleanup_(manager_freep) Manager *m = NULL; int r; @@ -1057,11 +1081,9 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags, } if (!FLAGS_SET(test_run_flags, MANAGER_TEST_DONT_OPEN_EXECUTOR)) { - m->executor_fd = pin_callout_binary(SYSTEMD_EXECUTOR_BINARY_PATH, &m->executor_path); - if (m->executor_fd < 0) - return log_debug_errno(m->executor_fd, "Failed to pin executor binary: %m"); - - log_debug("Using systemd-executor binary from '%s'.", m->executor_path); + r = pin_executor_binary(&m->executor_fd); + if (r < 0) + return r; } /* Note that we do not set up the notify fd here. We do that after deserialization, @@ -1797,7 +1819,6 @@ Manager* manager_free(Manager *m) { safe_close(m->restrict_fsaccess_bss_map_fd); safe_close(m->executor_fd); - free(m->executor_path); return mfree(m); } diff --git a/src/core/manager.h b/src/core/manager.h index e655e168c6..304124de04 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -505,7 +505,6 @@ typedef struct Manager { /* Pin the systemd-executor binary, so that it never changes until re-exec, ensuring we don't have * serialization/deserialization compatibility issues during upgrades. */ - char *executor_path; int executor_fd; unsigned soft_reboots_count; diff --git a/src/core/meson.build b/src/core/meson.build index af50a2a4fa..6e68a59d20 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -189,17 +189,38 @@ libcore = shared_library( install : true, install_dir : pkglibdir) -executor_libs = get_option('link-executor-shared') ? \ - [ - libcore, - libshared, - ] : [ - libc_wrapper_static, - libcore_static, - libshared_static, - libbasic_static, - libsystemd_static, +core_libs_static = [ + libc_wrapper_static, + libcore_static, + libshared_static, + libbasic_static, + libsystemd_static, +] +core_libs_shared = [ + libcore, + libshared, +] + +systemd_deps = [ + libapparmor_cflags, + libkmod_cflags, + libmount_cflags, + libseccomp_cflags, + libselinux_cflags, +] + +link_executor_shared = get_option('link-executor-shared') + +executor_libs = link_executor_shared == 'true' ? core_libs_shared : core_libs_static + +if link_executor_shared == 'single' + systemd_sources += systemd_executor_sources + systemd_deps += [ + libbpf_cflags, + libcryptsetup_cflags, + libpam_cflags, ] +endif executables += [ libexec_template + { @@ -207,33 +228,10 @@ executables += [ 'dbus' : true, 'public' : true, 'sources' : systemd_sources, - 'link_with' : [ - libcore, - libshared, - ], - 'dependencies' : [ - libapparmor_cflags, - libkmod_cflags, - libmount_cflags, - libseccomp_cflags, - libselinux_cflags, - ], - }, - libexec_template + { - 'name' : 'systemd-executor', - 'public' : true, - 'sources' : systemd_executor_sources, - 'link_with' : executor_libs, - 'dependencies' : [ - libapparmor_cflags, - libbpf_cflags, - libcryptsetup_cflags, - libmount_cflags, - libpam_cflags, - libseccomp_cflags, - libselinux_cflags, - ], + 'link_with' : core_libs_shared, + 'dependencies' : systemd_deps, }, + fuzz_template + { 'sources' : files('fuzz-unit-file.c'), 'link_with' : [ @@ -258,6 +256,31 @@ executables += [ }, ] +if link_executor_shared == 'single' + # Symlink for external callers + install_symlink('systemd-executor', + pointing_to : 'systemd', + install_dir : libexecdir) +else + executables += [ + libexec_template + { + 'name' : 'systemd-executor', + 'public' : true, + 'sources' : systemd_executor_sources, + 'link_with' : executor_libs, + 'dependencies' : [ + libapparmor_cflags, + libbpf_cflags, + libcryptsetup_cflags, + libmount_cflags, + libpam_cflags, + libseccomp_cflags, + libselinux_cflags, + ], + }, + ] +endif + in_files = [['system.conf', pkgconfigfiledir], ['user.conf', pkgconfigfiledir], ['org.freedesktop.systemd1.policy', polkitpolicydir]]