X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=execute.c;h=02f53dc4855b99089c042cdd92df921038b6d98c;hb=e2c76839a3f6444072ae452605204c7113ffdc37;hp=bdb0f921794ddb612f821861a0087e15aa3474d7;hpb=81a2b7ceda7100fbc0dd8ce423b9599e03656851;p=elogind.git diff --git a/execute.c b/execute.c index bdb0f9217..02f53dc48 100644 --- a/execute.c +++ b/execute.c @@ -42,6 +42,7 @@ #include "log.h" #include "ioprio.h" #include "securebits.h" +#include "cgroup.h" static int close_fds(int except[], unsigned n_except) { DIR *d; @@ -136,6 +137,7 @@ static int shift_fds(int fds[], unsigned n_fds) { static int flags_fds(int fds[], unsigned n_fds, bool nonblock) { unsigned i; + int r; if (n_fds <= 0) return 0; @@ -145,27 +147,16 @@ static int flags_fds(int fds[], unsigned n_fds, bool nonblock) { /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */ for (i = 0; i < n_fds; i++) { - int flags; - - if ((flags = fcntl(fds[i], F_GETFL, 0)) < 0) - return -errno; - if (nonblock) - flags |= O_NONBLOCK; - else - flags &= ~O_NONBLOCK; - - if (fcntl(fds[i], F_SETFL, flags) < 0) - return -errno; + if ((r = fd_nonblock(fds[i], nonblock)) < 0) + return r; /* We unconditionally drop FD_CLOEXEC from the fds, * since after all we want to pass these fds to our * children */ - if ((flags = fcntl(fds[i], F_GETFD, 0)) < 0) - return -errno; - if (fcntl(fds[i], F_SETFD, flags &~FD_CLOEXEC) < 0) - return -errno; + if ((r = fd_cloexec(fds[i], false)) < 0) + return r; } return 0; @@ -461,9 +452,13 @@ static int enforce_user(const ExecContext *context, uid_t uid) { /* First step: If we need to keep capabilities but * drop privileges we need to make sure we keep our * caps, whiel we drop priviliges. */ - if (uid != 0) - if (prctl(PR_SET_SECUREBITS, context->secure_bits|SECURE_KEEP_CAPS) < 0) - return -errno; + if (uid != 0) { + int sb = context->secure_bits|SECURE_KEEP_CAPS; + + if (prctl(PR_GET_SECUREBITS) != sb) + if (prctl(PR_SET_SECUREBITS, sb) < 0) + return -errno; + } /* Second step: set the capabilites. This will reduce * the capabilities to the minimum we need. */ @@ -504,9 +499,11 @@ int exec_spawn(const ExecCommand *command, int *fds, unsigned n_fds, bool apply_permissions, bool apply_chroot, + CGroupBonding *cgroup_bondings, pid_t *ret) { pid_t pid; + int r; assert(command); assert(context); @@ -515,11 +512,15 @@ int exec_spawn(const ExecCommand *command, log_debug("About to execute %s", command->path); + if (cgroup_bondings) + if ((r = cgroup_bonding_realize_list(cgroup_bondings))) + return r; + if ((pid = fork()) < 0) return -errno; if (pid == 0) { - int i, r; + int i; sigset_t ss; const char *username = NULL, *home = NULL; uid_t uid = (uid_t) -1; @@ -552,6 +553,12 @@ int exec_spawn(const ExecCommand *command, goto fail; } + if (cgroup_bondings) + if ((r = cgroup_bonding_install_list(cgroup_bondings, 0)) < 0) { + r = EXIT_CGROUP; + goto fail; + } + if (context->oom_adjust_set) { char t[16]; @@ -671,10 +678,15 @@ int exec_spawn(const ExecCommand *command, goto fail; } - if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) { - r = EXIT_SECUREBITS; - goto fail; - } + /* PR_GET_SECUREBITS is not priviliged, while + * PR_SET_SECUREBITS is. So to suppress + * potential EPERMs we'll try not to call + * PR_SET_SECUREBITS unless necessary. */ + if (prctl(PR_GET_SECUREBITS) != context->secure_bits) + if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) { + r = EXIT_SECUREBITS; + goto fail; + } if (context->capabilities) if (cap_set_proc(context->capabilities) < 0) {