diff options
-rw-r--r-- | src/basic/process-util.c | 3 | ||||
-rw-r--r-- | src/core/execute.c | 73 | ||||
-rw-r--r-- | src/network/networkd-link.c | 2 | ||||
-rw-r--r-- | src/network/networkd-route.c | 13 | ||||
-rw-r--r-- | src/systemctl/systemctl.c | 142 | ||||
-rw-r--r-- | src/test/test-process-util.c | 79 |
6 files changed, 166 insertions, 146 deletions
diff --git a/src/basic/process-util.c b/src/basic/process-util.c index f6bde20fc5..08fa98bb9e 100644 --- a/src/basic/process-util.c +++ b/src/basic/process-util.c @@ -325,9 +325,6 @@ static int get_process_id(pid_t pid, const char *field, uid_t *uid) { assert(field); assert(uid); - if (pid == 0) - return getuid(); - p = procfs_file_alloca(pid, "status"); f = fopen(p, "re"); if (!f) { diff --git a/src/core/execute.c b/src/core/execute.c index 802f14d575..c20650626c 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -799,7 +799,7 @@ static int setup_pam( const char *user, uid_t uid, const char *tty, - char ***pam_env, + char ***env, int fds[], unsigned n_fds) { static const struct pam_conv conv = { @@ -818,7 +818,7 @@ static int setup_pam( assert(name); assert(user); - assert(pam_env); + assert(env); /* We set up PAM in the parent process, then fork. The child * will then stay around until killed via PR_GET_PDEATHSIG or @@ -846,6 +846,12 @@ static int setup_pam( goto fail; } + STRV_FOREACH(e, *env) { + pam_code = pam_putenv(handle, *e); + if (pam_code != PAM_SUCCESS) + goto fail; + } + pam_code = pam_acct_mgmt(handle, flags); if (pam_code != PAM_SUCCESS) goto fail; @@ -966,8 +972,8 @@ static int setup_pam( if (!barrier_place_and_sync(&barrier)) log_error("PAM initialization failed"); - *pam_env = e; - e = NULL; + strv_free(*env); + *env = e; return 0; @@ -1464,7 +1470,7 @@ static int exec_child( char **files_env, int *exit_status) { - _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL; + _cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL; _cleanup_free_ char *mac_selinux_context_net = NULL; const char *username = NULL, *home = NULL, *shell = NULL, *wd; uid_t uid = UID_INVALID; @@ -1715,6 +1721,30 @@ static int exec_child( } } + r = build_environment(context, params, n_fds, home, username, shell, &our_env); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return r; + } + + r = build_pass_environment(context, &pass_env); + if (r < 0) { + *exit_status = EXIT_MEMORY; + return r; + } + + accum_env = strv_env_merge(5, + params->environment, + our_env, + pass_env, + context->environment, + files_env, + NULL); + if (!accum_env) { + *exit_status = EXIT_MEMORY; + return -ENOMEM; + } + umask(context->umask); if (params->apply_permissions && !command->privileged) { @@ -1751,7 +1781,7 @@ static int exec_child( #endif #ifdef HAVE_PAM if (context->pam_name && username) { - r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds); + r = setup_pam(context->pam_name, username, uid, context->tty_path, &accum_env, fds, n_fds); if (r < 0) { *exit_status = EXIT_PAM; return r; @@ -1997,38 +2027,13 @@ static int exec_child( #endif } - r = build_environment(context, params, n_fds, home, username, shell, &our_env); - if (r < 0) { - *exit_status = EXIT_MEMORY; - return r; - } - - r = build_pass_environment(context, &pass_env); - if (r < 0) { - *exit_status = EXIT_MEMORY; - return r; - } - - final_env = strv_env_merge(6, - params->environment, - our_env, - pass_env, - context->environment, - files_env, - pam_env, - NULL); - if (!final_env) { - *exit_status = EXIT_MEMORY; - return -ENOMEM; - } - - final_argv = replace_env_argv(argv, final_env); + final_argv = replace_env_argv(argv, accum_env); if (!final_argv) { *exit_status = EXIT_MEMORY; return -ENOMEM; } - final_env = strv_env_clean(final_env); + accum_env = strv_env_clean(accum_env); if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) { _cleanup_free_ char *line; @@ -2045,7 +2050,7 @@ static int exec_child( } } - execve(command->path, final_argv, final_env); + execve(command->path, final_argv, accum_env); *exit_status = EXIT_EXEC; return -errno; } diff --git a/src/network/networkd-link.c b/src/network/networkd-link.c index 0302f57f26..044f934e5f 100644 --- a/src/network/networkd-link.c +++ b/src/network/networkd-link.c @@ -2005,7 +2005,7 @@ static int link_joined(Link *link) { log_link_error_errno(link, r, "Could not set bridge message: %m"); } - if (link->network->bridge || streq("bridge", link->kind)) { + if (link->network->bridge || streq_ptr("bridge", link->kind)) { r = link_set_bridge_vlan(link); if (r < 0) log_link_error_errno(link, r, "Could not set bridge vlan: %m"); diff --git a/src/network/networkd-route.c b/src/network/networkd-route.c index 52037f9c6d..cedaf47cf8 100644 --- a/src/network/networkd-route.c +++ b/src/network/networkd-route.c @@ -795,6 +795,7 @@ int config_parse_route_priority(const char *unit, void *userdata) { Network *network = userdata; _cleanup_route_free_ Route *n = NULL; + uint32_t k; int r; assert(filename); @@ -807,12 +808,14 @@ int config_parse_route_priority(const char *unit, if (r < 0) return r; - r = config_parse_uint32(unit, filename, line, section, - section_line, lvalue, ltype, - rvalue, &n->priority, userdata); - if (r < 0) - return r; + r = safe_atou32(rvalue, &k); + if (r < 0) { + log_syntax(unit, LOG_ERR, filename, line, r, + "Could not parse route priority \"%s\", ignoring assignment: %m", rvalue); + return 0; + } + n->priority = k; n = NULL; return 0; diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 914dba36dc..784c1cd7b5 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -3274,6 +3274,18 @@ static int start_special(int argc, char *argv[], void *userdata) { return start_unit(argc, argv, userdata); } +static int start_system_special(int argc, char *argv[], void *userdata) { + /* Like start_special above, but raises an error when running in user mode */ + + if (arg_scope != UNIT_FILE_SYSTEM) { + log_error("Bad action for %s mode.", + arg_scope == UNIT_FILE_GLOBAL ? "--global" : "--user"); + return -EINVAL; + } + + return start_special(argc, argv, userdata); +} + static int check_unit_generic(int code, const UnitActiveState good_states[], int nb_states, char **args) { _cleanup_strv_free_ char **names = NULL; UnitActiveState active_state; @@ -7539,71 +7551,71 @@ static int systemctl_main(int argc, char *argv[]) { static const Verb verbs[] = { { "list-units", VERB_ANY, VERB_ANY, VERB_DEFAULT|VERB_NOCHROOT, list_units }, - { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, - { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets }, - { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers }, - { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs }, - { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines }, - { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, trivial_method }, - { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job }, - { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ - { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */ - { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, - { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */ - { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ - { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */ - { "isolate", 2, 2, VERB_NOCHROOT, start_unit }, - { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit }, - { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, - { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, - { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed }, - { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, - { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat }, - { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, - { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, - { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, - { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, - { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment }, - { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, - { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, - { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment}, - { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_special }, - { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_special }, - { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special }, - { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed }, - { "enable", 2, VERB_ANY, 0, enable_unit }, - { "disable", 2, VERB_ANY, 0, enable_unit }, - { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, - { "reenable", 2, VERB_ANY, 0, enable_unit }, - { "preset", 2, VERB_ANY, 0, enable_unit }, - { "preset-all", VERB_ANY, 1, 0, preset_all }, - { "mask", 2, VERB_ANY, 0, enable_unit }, - { "unmask", 2, VERB_ANY, 0, enable_unit }, - { "link", 2, VERB_ANY, 0, enable_unit }, - { "revert", 2, VERB_ANY, 0, enable_unit }, - { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root }, - { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies }, - { "set-default", 2, 2, 0, set_default }, - { "get-default", VERB_ANY, 1, 0, get_default }, - { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property }, - { "is-system-running", VERB_ANY, 1, 0, is_system_running }, - { "add-wants", 3, VERB_ANY, 0, add_dependency }, - { "add-requires", 3, VERB_ANY, 0, add_dependency }, - { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit }, + { "list-unit-files", VERB_ANY, VERB_ANY, 0, list_unit_files }, + { "list-sockets", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_sockets }, + { "list-timers", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_timers }, + { "list-jobs", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_jobs }, + { "list-machines", VERB_ANY, VERB_ANY, VERB_NOCHROOT, list_machines }, + { "clear-jobs", VERB_ANY, 1, VERB_NOCHROOT, trivial_method }, + { "cancel", VERB_ANY, VERB_ANY, VERB_NOCHROOT, cancel_job }, + { "start", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "stop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "condstop", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ + { "reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "reload-or-try-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatbility with old systemctl <= 228 */ + { "try-reload-or-restart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, + { "force-reload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with SysV */ + { "condreload", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with ALTLinux */ + { "condrestart", 2, VERB_ANY, VERB_NOCHROOT, start_unit }, /* For compatibility with RH */ + { "isolate", 2, 2, VERB_NOCHROOT, start_unit }, + { "kill", 2, VERB_ANY, VERB_NOCHROOT, kill_unit }, + { "is-active", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, + { "check", 2, VERB_ANY, VERB_NOCHROOT, check_unit_active }, + { "is-failed", 2, VERB_ANY, VERB_NOCHROOT, check_unit_failed }, + { "show", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, + { "cat", 2, VERB_ANY, VERB_NOCHROOT, cat }, + { "status", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, + { "help", VERB_ANY, VERB_ANY, VERB_NOCHROOT, show }, + { "daemon-reload", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, + { "daemon-reexec", VERB_ANY, 1, VERB_NOCHROOT, daemon_reload }, + { "show-environment", VERB_ANY, 1, VERB_NOCHROOT, show_environment }, + { "set-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, + { "unset-environment", 2, VERB_ANY, VERB_NOCHROOT, set_environment }, + { "import-environment", VERB_ANY, VERB_ANY, VERB_NOCHROOT, import_environment }, + { "halt", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "poweroff", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "reboot", VERB_ANY, 2, VERB_NOCHROOT, start_system_special }, + { "kexec", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "suspend", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "hibernate", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "hybrid-sleep", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "default", VERB_ANY, 1, VERB_NOCHROOT, start_special }, + { "rescue", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "emergency", VERB_ANY, 1, VERB_NOCHROOT, start_system_special }, + { "exit", VERB_ANY, 2, VERB_NOCHROOT, start_special }, + { "reset-failed", VERB_ANY, VERB_ANY, VERB_NOCHROOT, reset_failed }, + { "enable", 2, VERB_ANY, 0, enable_unit }, + { "disable", 2, VERB_ANY, 0, enable_unit }, + { "is-enabled", 2, VERB_ANY, 0, unit_is_enabled }, + { "reenable", 2, VERB_ANY, 0, enable_unit }, + { "preset", 2, VERB_ANY, 0, enable_unit }, + { "preset-all", VERB_ANY, 1, 0, preset_all }, + { "mask", 2, VERB_ANY, 0, enable_unit }, + { "unmask", 2, VERB_ANY, 0, enable_unit }, + { "link", 2, VERB_ANY, 0, enable_unit }, + { "revert", 2, VERB_ANY, 0, enable_unit }, + { "switch-root", 2, VERB_ANY, VERB_NOCHROOT, switch_root }, + { "list-dependencies", VERB_ANY, 2, VERB_NOCHROOT, list_dependencies }, + { "set-default", 2, 2, 0, set_default }, + { "get-default", VERB_ANY, 1, 0, get_default }, + { "set-property", 3, VERB_ANY, VERB_NOCHROOT, set_property }, + { "is-system-running", VERB_ANY, 1, 0, is_system_running }, + { "add-wants", 3, VERB_ANY, 0, add_dependency }, + { "add-requires", 3, VERB_ANY, 0, add_dependency }, + { "edit", 2, VERB_ANY, VERB_NOCHROOT, edit }, {} }; diff --git a/src/test/test-process-util.c b/src/test/test-process-util.c index 4616314200..8bb5f6e3a3 100644 --- a/src/test/test-process-util.c +++ b/src/test/test-process-util.c @@ -28,72 +28,66 @@ #include "architecture.h" #include "log.h" #include "macro.h" +#include "parse-util.h" #include "process-util.h" +#include "stdio-util.h" #include "string-util.h" #include "terminal-util.h" #include "util.h" #include "virt.h" -static void test_get_process_comm(void) { +static void test_get_process_comm(pid_t pid) { struct stat st; _cleanup_free_ char *a = NULL, *c = NULL, *d = NULL, *f = NULL, *i = NULL, *cwd = NULL, *root = NULL; _cleanup_free_ char *env = NULL; + char path[strlen("/proc//comm") + DECIMAL_STR_MAX(pid_t)]; pid_t e; uid_t u; gid_t g; dev_t h; int r; - pid_t me; - if (stat("/proc/1/comm", &st) == 0) { - assert_se(get_process_comm(1, &a) >= 0); - log_info("pid1 comm: '%s'", a); + xsprintf(path, "/proc/"PID_FMT"/comm", pid); + + if (stat(path, &st) == 0) { + assert_se(get_process_comm(pid, &a) >= 0); + log_info("PID"PID_FMT" comm: '%s'", pid, a); } else - log_warning("/proc/1/comm does not exist."); + log_warning("%s not exist.", path); - assert_se(get_process_cmdline(1, 0, true, &c) >= 0); - log_info("pid1 cmdline: '%s'", c); + assert_se(get_process_cmdline(pid, 0, true, &c) >= 0); + log_info("PID"PID_FMT" cmdline: '%s'", pid, c); - assert_se(get_process_cmdline(1, 8, false, &d) >= 0); - log_info("pid1 cmdline truncated: '%s'", d); + assert_se(get_process_cmdline(pid, 8, false, &d) >= 0); + log_info("PID"PID_FMT" cmdline truncated: '%s'", pid, d); - assert_se(get_process_ppid(1, &e) >= 0); - log_info("pid1 ppid: "PID_FMT, e); - assert_se(e == 0); + assert_se(get_process_ppid(pid, &e) >= 0); + log_info("PID"PID_FMT" PPID: "PID_FMT, pid, e); + assert_se(pid == 1 ? e == 0 : e > 0); - assert_se(is_kernel_thread(1) == 0); + assert_se(is_kernel_thread(pid) == 0 || pid != 1); - r = get_process_exe(1, &f); + r = get_process_exe(pid, &f); assert_se(r >= 0 || r == -EACCES); - log_info("pid1 exe: '%s'", strna(f)); - - assert_se(get_process_uid(1, &u) == 0); - log_info("pid1 uid: "UID_FMT, u); - assert_se(u == 0); - - assert_se(get_process_gid(1, &g) == 0); - log_info("pid1 gid: "GID_FMT, g); - assert_se(g == 0); + log_info("PID"PID_FMT" exe: '%s'", pid, strna(f)); - me = getpid(); - - r = get_process_cwd(me, &cwd); - assert_se(r >= 0 || r == -EACCES); - log_info("pid1 cwd: '%s'", cwd); + assert_se(get_process_uid(pid, &u) == 0); + log_info("PID"PID_FMT" UID: "UID_FMT, pid, u); + assert_se(u == 0 || pid != 1); - r = get_process_root(me, &root); - assert_se(r >= 0 || r == -EACCES); - log_info("pid1 root: '%s'", root); + assert_se(get_process_gid(pid, &g) == 0); + log_info("PID"PID_FMT" GID: "GID_FMT, pid, g); + assert_se(g == 0 || pid != 1); - r = get_process_environ(me, &env); + r = get_process_environ(pid, &env); assert_se(r >= 0 || r == -EACCES); - log_info("self strlen(environ): '%zu'", strlen(env)); + log_info("PID"PID_FMT" strlen(environ): %zi", pid, env ? (ssize_t)strlen(env) : (ssize_t)-errno); if (!detect_container()) - assert_se(get_ctty_devnr(1, &h) == -ENXIO); + assert_se(get_ctty_devnr(pid, &h) == -ENXIO || pid != 1); - getenv_for_pid(1, "PATH", &i); - log_info("pid1 $PATH: '%s'", strna(i)); + getenv_for_pid(pid, "PATH", &i); + log_info("PID"PID_FMT" $PATH: '%s'", pid, strna(i)); } static void test_pid_is_unwaited(void) { @@ -157,7 +151,16 @@ int main(int argc, char *argv[]) { log_parse_environment(); log_open(); - test_get_process_comm(); + if (argc > 1) { + pid_t pid = 0; + + (void) parse_pid(argv[1], &pid); + test_get_process_comm(pid); + } else { + test_get_process_comm(1); + test_get_process_comm(getpid()); + } + test_pid_is_unwaited(); test_pid_is_alive(); test_personality(); |