[systemd-commits] 3 commits - src/execute.c src/exit-status.c src/exit-status.h src/log.c src/log.h

Michal Schmidt michich at kemper.freedesktop.org
Wed Nov 16 16:39:25 PST 2011


 src/execute.c     |  147 ++++++++++++++++++++++++++++++++++++++++--------------
 src/exit-status.c |    3 +
 src/exit-status.h |    3 -
 src/log.c         |    4 +
 src/log.h         |    1 
 5 files changed, 120 insertions(+), 38 deletions(-)

New commits:
commit 4c2630ebf23b6348174f0bdf1110e90efe45259c
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Thu Nov 17 00:21:16 2011 +0100

    execute: log errors from "sd(EXEC)"
    
    To give the administrator more hints about failures occuring in spawning
    of commands than just the exit code, log the strerror.
    All fds are closed, so reopen the log.
    
    Related-to: https://bugzilla.redhat.com/show_bug.cgi?id=752901

diff --git a/src/execute.c b/src/execute.c
index 2039861..481725d 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), &param) < 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 8ed1a0e..ab8907d 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 3e977b1..44ef879 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;
 

commit 9ba353983adc026b75a503c1381f6e5c8062f3e0
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Thu Nov 17 00:16:22 2011 +0100

    execute: make setup_pam() return -errno when possible
    
    The only caller currently checks if the result is non-zero,
    so nothing changes there.

diff --git a/src/execute.c b/src/execute.c
index 0651014..2039861 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -716,6 +716,7 @@ static int setup_pam(
         pam_handle_t *handle = NULL;
         sigset_t ss, old_ss;
         int pam_code = PAM_SUCCESS;
+        int err;
         char **e = NULL;
         bool close_session = false;
         pid_t pam_pid = 0, parent_pid;
@@ -835,6 +836,11 @@ static int setup_pam(
         return 0;
 
 fail:
+        if (pam_code != PAM_SUCCESS)
+                err = -EPERM;  /* PAM errors do not map to errno */
+        else
+                err = -errno;
+
         if (handle) {
                 if (close_session)
                         pam_code = pam_close_session(handle, PAM_DATA_SILENT);
@@ -851,7 +857,7 @@ fail:
                 kill(pam_pid, SIGCONT);
         }
 
-        return EXIT_PAM;
+        return err;
 }
 #endif
 

commit 4d8a7798e7f12c6400495cbc4d0ad57ed20ce90a
Author: Michal Schmidt <mschmidt at redhat.com>
Date:   Wed Nov 16 23:45:01 2011 +0100

    execute: avoid logging to closed fds
    
    Several functions called from the "sd(EXEC)" process try to log messages
    when all the file descriptors are already closed, including the logging
    ones. The logging functions do not expect their fds to be closed and
    they hit an assertion failure. The failure wants to be logged too,
    so there is an infinite recursion, ended by a SIGSEGV.
    
    When we close all fds, we must let log.c know about it.

diff --git a/src/execute.c b/src/execute.c
index 250d53a..0651014 100644
--- a/src/execute.c
+++ b/src/execute.c
@@ -1016,6 +1016,7 @@ int exec_spawn(ExecCommand *command,
                 /* Close sockets very early to make sure we don't
                  * 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) {
                         r = EXIT_FDS;
diff --git a/src/log.c b/src/log.c
index b8ce122..5c5b734 100644
--- a/src/log.c
+++ b/src/log.c
@@ -237,6 +237,10 @@ void log_close(void) {
         log_close_syslog();
 }
 
+void log_forget_fds(void) {
+        console_fd = kmsg_fd = syslog_fd = -1;
+}
+
 void log_set_max_level(int level) {
         assert((level & LOG_PRIMASK) == level);
 
diff --git a/src/log.h b/src/log.h
index c402afb..9942e3e 100644
--- a/src/log.h
+++ b/src/log.h
@@ -57,6 +57,7 @@ int log_get_max_level(void);
 
 int log_open(void);
 void log_close(void);
+void log_forget_fds(void);
 
 void log_close_syslog(void);
 void log_close_kmsg(void);



More information about the systemd-commits mailing list