X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fexecute.c;h=bbc430e0556d685e79a6188edfeb257d3ceb328e;hp=179ca7e55cfa23ae021e5719aae3e7c6bf42e863;hb=f96096dbbf0cc7335babf0386b8888431cd70728;hpb=b30e2f4c18ad81b04e4314fd191a5d458553773c diff --git a/src/core/execute.c b/src/core/execute.c index 179ca7e55..bbc430e05 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -6,16 +6,16 @@ Copyright 2010 Lennart Poettering systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. systemd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. + Lesser General Public License for more details. - You should have received a copy of the GNU General Public License + You should have received a copy of the GNU Lesser General Public License along with systemd; If not, see . ***/ @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef HAVE_PAM #include @@ -58,6 +59,9 @@ #include "utmp-wtmp.h" #include "def.h" #include "loopback-setup.h" +#include "path-util.h" + +#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC) /* This assumes there is a 'tty' group */ #define TTY_MODE 0620 @@ -701,6 +705,7 @@ static int null_conv( static int setup_pam( const char *name, const char *user, + uid_t uid, const char *tty, char ***pam_env, int fds[], unsigned n_fds) { @@ -779,10 +784,17 @@ static int setup_pam( open here that have been opened by PAM. */ close_many(fds, n_fds); - /* Wait until our parent died. This will most likely - * not work since the kernel does not allow - * unprivileged parents kill their privileged children - * this way. We rely on the control groups kill logic + /* Drop privileges - we don't need any to pam_close_session + * and this will make PR_SET_PDEATHSIG work in most cases. + * If this fails, ignore the error - but expect sd-pam threads + * to fail to exit normally */ + if (setresuid(uid, uid, uid) < 0) + log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r)); + + /* Wait until our parent died. This will only work if + * the above setresuid() succeeds, otherwise the kernel + * will not allow unprivileged parents kill their privileged + * children this way. We rely on the control groups kill logic * to do the rest for us. */ if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0) goto child_finish; @@ -858,68 +870,6 @@ fail: } #endif -static int do_capability_bounding_set_drop(uint64_t drop) { - unsigned long i; - cap_t old_cap = NULL, new_cap = NULL; - cap_flag_value_t fv; - int r; - - /* If we are run as PID 1 we will lack CAP_SETPCAP by default - * in the effective set (yes, the kernel drops that when - * executing init!), so get it back temporarily so that we can - * call PR_CAPBSET_DROP. */ - - old_cap = cap_get_proc(); - if (!old_cap) - return -errno; - - if (cap_get_flag(old_cap, CAP_SETPCAP, CAP_EFFECTIVE, &fv) < 0) { - r = -errno; - goto finish; - } - - if (fv != CAP_SET) { - static const cap_value_t v = CAP_SETPCAP; - - new_cap = cap_dup(old_cap); - if (!new_cap) { - r = -errno; - goto finish; - } - - if (cap_set_flag(new_cap, CAP_EFFECTIVE, 1, &v, CAP_SET) < 0) { - r = -errno; - goto finish; - } - - if (cap_set_proc(new_cap) < 0) { - r = -errno; - goto finish; - } - } - - for (i = 0; i <= cap_last_cap(); i++) - if (drop & ((uint64_t) 1ULL << (uint64_t) i)) { - if (prctl(PR_CAPBSET_DROP, i) < 0) { - r = -errno; - goto finish; - } - } - - r = 0; - -finish: - if (new_cap) - cap_free(new_cap); - - if (old_cap) { - cap_set_proc(old_cap); - cap_free(old_cap); - } - - return r; -} - static void rename_process_from_path(const char *path) { char process_name[11]; const char *p; @@ -928,7 +878,7 @@ static void rename_process_from_path(const char *path) { /* This resulting string must fit in 10 chars (i.e. the length * of "/sbin/init") to look pretty in /bin/ps */ - p = file_name_from_path(path); + p = path_get_file_name(path); if (isempty(p)) { rename_process("(...)"); return; @@ -962,6 +912,8 @@ int exec_spawn(ExecCommand *command, bool confirm_spawn, CGroupBonding *cgroup_bondings, CGroupAttribute *cgroup_attributes, + const char *cgroup_suffix, + int idle_pipe[2], pid_t *ret) { pid_t pid; @@ -1049,6 +1001,15 @@ int exec_spawn(ExecCommand *command, goto fail_child; } + if (idle_pipe) { + if (idle_pipe[1] >= 0) + close_nointr_nofail(idle_pipe[1]); + if (idle_pipe[0] >= 0) { + fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC); + close_nointr_nofail(idle_pipe[0]); + } + } + /* Close sockets very early to make sure we don't * block init reexecution because it cannot bind its * sockets */ @@ -1140,21 +1101,21 @@ int exec_spawn(ExecCommand *command, } if (!keep_stdout) { - err = setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); + err = setup_output(context, socket_fd, path_get_file_name(command->path), apply_tty_stdin); if (err < 0) { r = EXIT_STDOUT; goto fail_child; } } - err = setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin); + err = setup_error(context, socket_fd, path_get_file_name(command->path), apply_tty_stdin); if (err < 0) { r = EXIT_STDERR; goto fail_child; } if (cgroup_bondings) { - err = cgroup_bonding_install_list(cgroup_bondings, 0); + err = cgroup_bonding_install_list(cgroup_bondings, 0, cgroup_suffix); if (err < 0) { r = EXIT_CGROUP; goto fail_child; @@ -1168,22 +1129,9 @@ int exec_spawn(ExecCommand *command, char_array_0(t); if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) { - /* Compatibility with Linux <= 2.6.35 */ - - int adj; - - adj = (context->oom_score_adjust * -OOM_DISABLE) / OOM_SCORE_ADJ_MAX; - adj = CLAMP(adj, OOM_DISABLE, OOM_ADJUST_MAX); - - snprintf(t, sizeof(t), "%i", adj); - char_array_0(t); - - if (write_one_line_file("/proc/self/oom_adj", t) < 0 - && errno != EACCES) { - err = -errno; - r = EXIT_OOM_ADJUST; - goto fail_child; - } + err = -errno; + r = EXIT_OOM_ADJUST; + goto fail_child; } } @@ -1222,7 +1170,7 @@ int exec_spawn(ExecCommand *command, goto fail_child; } - if (context->timer_slack_nsec_set) + if (context->timer_slack_nsec != (nsec_t) -1) if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) { err = -errno; r = EXIT_TIMERSLACK; @@ -1281,7 +1229,7 @@ int exec_spawn(ExecCommand *command, #ifdef HAVE_PAM if (context->pam_name && username) { - err = setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds); + err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds); if (err < 0) { r = EXIT_PAM; goto fail_child; @@ -1367,7 +1315,7 @@ int exec_spawn(ExecCommand *command, if (!context->rlimit[i]) continue; - if (setrlimit(i, context->rlimit[i]) < 0) { + if (setrlimit_closest(i, context->rlimit[i]) < 0) { err = -errno; r = EXIT_LIMITS; goto fail_child; @@ -1375,7 +1323,7 @@ int exec_spawn(ExecCommand *command, } if (context->capability_bounding_set_drop) { - err = do_capability_bounding_set_drop(context->capability_bounding_set_drop); + err = capability_bounding_set_drop(context->capability_bounding_set_drop, false); if (err < 0) { r = EXIT_CAPABILITIES; goto fail_child; @@ -1505,7 +1453,7 @@ int exec_spawn(ExecCommand *command, * sure that when we kill the cgroup the process will be * killed too). */ if (cgroup_bondings) - cgroup_bonding_install_list(cgroup_bondings, pid); + cgroup_bonding_install_list(cgroup_bondings, pid, cgroup_suffix); log_debug("Forked %s as %lu", command->path, (unsigned long) pid); @@ -1533,6 +1481,7 @@ void exec_context_init(ExecContext *c) { c->send_sigkill = true; c->control_group_persistent = -1; c->ignore_sigpipe = true; + c->timer_slack_nsec = (nsec_t) -1; } void exec_context_done(ExecContext *c) { @@ -1778,8 +1727,8 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) { fputs("\n", f); } - if (c->timer_slack_nsec_set) - fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, c->timer_slack_nsec); + if (c->timer_slack_nsec != (nsec_t) -1) + fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, (unsigned long)c->timer_slack_nsec); fprintf(f, "%sStandardInput: %s\n"