diff options
-rw-r--r-- | src/execute.c | 138 | ||||
-rw-r--r-- | src/exit-status.c | 3 | ||||
-rw-r--r-- | src/exit-status.h | 3 |
3 files changed, 107 insertions, 37 deletions
diff --git a/src/execute.c b/src/execute.c index 2039861782..481725d63d 100644 --- a/src/execute.c +++ b/src/execute.c @@ -989,7 +989,7 @@ int exec_spawn(ExecCommand *command, } if (pid == 0) { - int i; + int i, err; sigset_t ss; const char *username = NULL, *home = NULL; uid_t uid = (uid_t) -1; @@ -1015,6 +1015,7 @@ int exec_spawn(ExecCommand *command, if (sigemptyset(&ss) < 0 || sigprocmask(SIG_SETMASK, &ss, NULL) < 0) { + err = -errno; r = EXIT_SIGNAL_MASK; goto fail_child; } @@ -1023,14 +1024,16 @@ int exec_spawn(ExecCommand *command, * block init reexecution because it cannot bind its * sockets */ log_forget_fds(); - if (close_all_fds(socket_fd >= 0 ? &socket_fd : fds, - socket_fd >= 0 ? 1 : n_fds) < 0) { + err = close_all_fds(socket_fd >= 0 ? &socket_fd : fds, + socket_fd >= 0 ? 1 : n_fds); + if (err < 0) { r = EXIT_FDS; goto fail_child; } if (!context->same_pgrp) if (setsid() < 0) { + err = -errno; r = EXIT_SETSID; goto fail_child; } @@ -1038,12 +1041,14 @@ int exec_spawn(ExecCommand *command, if (context->tcpwrap_name) { if (socket_fd >= 0) if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) { + err = -EACCES; r = EXIT_TCPWRAP; goto fail_child; } for (i = 0; i < (int) n_fds; i++) { if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) { + err = -EACCES; r = EXIT_TCPWRAP; goto fail_child; } @@ -1059,11 +1064,14 @@ int exec_spawn(ExecCommand *command, /* Set up terminal for the question */ if ((r = setup_confirm_stdio(context, - &saved_stdin, &saved_stdout))) + &saved_stdin, &saved_stdout))) { + err = -errno; goto fail_child; + } /* Now ask the question. */ if (!(line = exec_command_line(argv))) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1072,18 +1080,21 @@ int exec_spawn(ExecCommand *command, free(line); if (r < 0 || response == 'n') { + err = -ECANCELED; r = EXIT_CONFIRM; goto fail_child; } else if (response == 's') { - r = 0; + err = r = 0; goto fail_child; } /* Release terminal for the question */ if ((r = restore_confirm_stdio(context, &saved_stdin, &saved_stdout, - &keep_stdin, &keep_stdout))) + &keep_stdin, &keep_stdout))) { + err = -errno; goto fail_child; + } } /* If a socket is connected to STDIN/STDOUT/STDERR, we @@ -1091,28 +1102,35 @@ int exec_spawn(ExecCommand *command, if (socket_fd >= 0) fd_nonblock(socket_fd, false); - if (!keep_stdin) - if (setup_input(context, socket_fd, apply_tty_stdin) < 0) { + if (!keep_stdin) { + err = setup_input(context, socket_fd, apply_tty_stdin); + if (err < 0) { r = EXIT_STDIN; goto fail_child; } + } - if (!keep_stdout) - if (setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) { + if (!keep_stdout) { + err = setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); + if (err < 0) { r = EXIT_STDOUT; goto fail_child; } + } - if (setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) { + err = setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); + if (err < 0) { r = EXIT_STDERR; goto fail_child; } - if (cgroup_bondings) - if (cgroup_bonding_install_list(cgroup_bondings, 0) < 0) { + if (cgroup_bondings) { + err = cgroup_bonding_install_list(cgroup_bondings, 0); + if (err < 0) { r = EXIT_CGROUP; goto fail_child; } + } if (context->oom_score_adjust_set) { char t[16]; @@ -1133,6 +1151,7 @@ int exec_spawn(ExecCommand *command, if (write_one_line_file("/proc/self/oom_adj", t) < 0 && errno != EACCES) { + err = -errno; r = EXIT_OOM_ADJUST; goto fail_child; } @@ -1141,6 +1160,7 @@ int exec_spawn(ExecCommand *command, if (context->nice_set) if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) { + err = -errno; r = EXIT_NICE; goto fail_child; } @@ -1153,6 +1173,7 @@ int exec_spawn(ExecCommand *command, if (sched_setscheduler(0, context->cpu_sched_policy | (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), ¶m) < 0) { + err = -errno; r = EXIT_SETSCHEDULER; goto fail_child; } @@ -1160,18 +1181,21 @@ int exec_spawn(ExecCommand *command, if (context->cpuset) if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) { + err = -errno; r = EXIT_CPUAFFINITY; goto fail_child; } if (context->ioprio_set) if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) { + err = -errno; r = EXIT_IOPRIO; goto fail_child; } if (context->timer_slack_nsec_set) if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) { + err = -errno; r = EXIT_TIMERSLACK; goto fail_child; } @@ -1181,36 +1205,45 @@ int exec_spawn(ExecCommand *command, if (context->user) { username = context->user; - if (get_user_creds(&username, &uid, &gid, &home) < 0) { + err = get_user_creds(&username, &uid, &gid, &home); + if (err < 0) { r = EXIT_USER; goto fail_child; } - if (is_terminal_input(context->std_input)) - if (chown_terminal(STDIN_FILENO, uid) < 0) { + if (is_terminal_input(context->std_input)) { + err = chown_terminal(STDIN_FILENO, uid); + if (err < 0) { r = EXIT_STDIN; goto fail_child; } + } - if (cgroup_bondings && context->control_group_modify) - if (cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid) < 0 || - cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid) < 0) { + if (cgroup_bondings && context->control_group_modify) { + err = cgroup_bonding_set_group_access_list(cgroup_bondings, 0755, uid, gid); + if (err >= 0) + err = cgroup_bonding_set_task_access_list(cgroup_bondings, 0644, uid, gid); + if (err < 0) { r = EXIT_CGROUP; goto fail_child; } + } } - if (apply_permissions) - if (enforce_groups(context, username, gid) < 0) { + if (apply_permissions) { + err = enforce_groups(context, username, gid); + if (err < 0) { r = EXIT_GROUP; goto fail_child; } + } umask(context->umask); #ifdef HAVE_PAM if (context->pam_name && username) { - if (setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds) != 0) { + err = setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds); + if (err < 0) { r = EXIT_PAM; goto fail_child; } @@ -1218,6 +1251,7 @@ int exec_spawn(ExecCommand *command, #endif if (context->private_network) { if (unshare(CLONE_NEWNET) < 0) { + err = -errno; r = EXIT_NETWORK; goto fail_child; } @@ -1229,23 +1263,28 @@ int exec_spawn(ExecCommand *command, strv_length(context->read_only_dirs) > 0 || strv_length(context->inaccessible_dirs) > 0 || context->mount_flags != MS_SHARED || - context->private_tmp) - if ((r = setup_namespace( - context->read_write_dirs, - context->read_only_dirs, - context->inaccessible_dirs, - context->private_tmp, - context->mount_flags)) < 0) + context->private_tmp) { + err = setup_namespace(context->read_write_dirs, + context->read_only_dirs, + context->inaccessible_dirs, + context->private_tmp, + context->mount_flags); + if (err < 0) { + r = EXIT_NAMESPACE; goto fail_child; + } + } if (apply_chroot) { if (context->root_directory) if (chroot(context->root_directory) < 0) { + err = -errno; r = EXIT_CHROOT; goto fail_child; } if (chdir(context->working_directory ? context->working_directory : "/") < 0) { + err = -errno; r = EXIT_CHDIR; goto fail_child; } @@ -1256,11 +1295,13 @@ int exec_spawn(ExecCommand *command, if (asprintf(&d, "%s/%s", context->root_directory ? context->root_directory : "", context->working_directory ? context->working_directory : "") < 0) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } if (chdir(d) < 0) { + err = -errno; free(d); r = EXIT_CHDIR; goto fail_child; @@ -1271,9 +1312,12 @@ int exec_spawn(ExecCommand *command, /* We repeat the fd closing here, to make sure that * nothing is leaked from the PAM modules */ - if (close_all_fds(fds, n_fds) < 0 || - shift_fds(fds, n_fds) < 0 || - flags_fds(fds, n_fds, context->non_blocking) < 0) { + err = close_all_fds(fds, n_fds); + if (err >= 0) + err = shift_fds(fds, n_fds); + if (err >= 0) + err = flags_fds(fds, n_fds, context->non_blocking); + if (err < 0) { r = EXIT_FDS; goto fail_child; } @@ -1285,22 +1329,27 @@ int exec_spawn(ExecCommand *command, continue; if (setrlimit(i, context->rlimit[i]) < 0) { + err = -errno; r = EXIT_LIMITS; goto fail_child; } } - if (context->capability_bounding_set_drop) - if (do_capability_bounding_set_drop(context->capability_bounding_set_drop) < 0) { + if (context->capability_bounding_set_drop) { + err = do_capability_bounding_set_drop(context->capability_bounding_set_drop); + if (err < 0) { r = EXIT_CAPABILITIES; goto fail_child; } + } - if (context->user) - if (enforce_user(context, uid) < 0) { + if (context->user) { + err = enforce_user(context, uid); + if (err < 0) { r = EXIT_USER; goto fail_child; } + } /* PR_GET_SECUREBITS is not privileged, while * PR_SET_SECUREBITS is. So to suppress @@ -1308,18 +1357,21 @@ int exec_spawn(ExecCommand *command, * PR_SET_SECUREBITS unless necessary. */ if (prctl(PR_GET_SECUREBITS) != context->secure_bits) if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) { + err = -errno; r = EXIT_SECUREBITS; goto fail_child; } if (context->capabilities) if (cap_set_proc(context->capabilities) < 0) { + err = -errno; r = EXIT_CAPABILITIES; goto fail_child; } } if (!(our_env = new0(char*, 7))) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1327,12 +1379,14 @@ int exec_spawn(ExecCommand *command, if (n_fds > 0) if (asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 || asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } if (home) if (asprintf(our_env + n_env++, "HOME=%s", home) < 0) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1340,6 +1394,7 @@ int exec_spawn(ExecCommand *command, if (username) if (asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 || asprintf(our_env + n_env++, "USER=%s", username) < 0) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1348,6 +1403,7 @@ int exec_spawn(ExecCommand *command, context->std_output == EXEC_OUTPUT_TTY || context->std_error == EXEC_OUTPUT_TTY) if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1362,11 +1418,13 @@ int exec_spawn(ExecCommand *command, files_env, pam_env, NULL))) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } if (!(final_argv = replace_env_argv(argv, final_env))) { + err = -ENOMEM; r = EXIT_MEMORY; goto fail_child; } @@ -1374,9 +1432,17 @@ int exec_spawn(ExecCommand *command, final_env = strv_env_clean(final_env); execve(command->path, final_argv, final_env); + err = -errno; r = EXIT_EXEC; fail_child: + if (r != 0) { + log_open(); + log_warning("Failed at step %s spawning %s: %s", + exit_status_to_string(r, EXIT_STATUS_SYSTEMD), + command->path, strerror(-err)); + } + strv_free(our_env); strv_free(final_env); strv_free(pam_env); diff --git a/src/exit-status.c b/src/exit-status.c index 8ed1a0e362..ab8907d32c 100644 --- a/src/exit-status.c +++ b/src/exit-status.c @@ -119,6 +119,9 @@ const char* exit_status_to_string(ExitStatus status, ExitStatusLevel level) { case EXIT_NETWORK: return "NETWORK"; + + case EXIT_NAMESPACE: + return "NAMESPACE"; } } diff --git a/src/exit-status.h b/src/exit-status.h index 3e977b10ef..44ef879562 100644 --- a/src/exit-status.h +++ b/src/exit-status.h @@ -65,7 +65,8 @@ typedef enum ExitStatus { EXIT_STDERR, EXIT_TCPWRAP, EXIT_PAM, - EXIT_NETWORK + EXIT_NETWORK, + EXIT_NAMESPACE } ExitStatus; |