execute.c revision 35b8ca3aaf8cb044ad76675dfcad89e000dd4a5c
d657c51f14601d0235434ffb78cf6ac0f27cc83cLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
220a21d38f675eb835f5758e3d23e896573aa5eaLennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering/***
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering This file is part of systemd.
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering Copyright 2010 Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt systemd is free software; you can redistribute it and/or modify it
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering under the terms of the GNU General Public License as published by
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering the Free Software Foundation; either version 2 of the License, or
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering (at your option) any later version.
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering systemd is distributed in the hope that it will be useful, but
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering General Public License for more details.
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering You should have received a copy of the GNU General Public License
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt along with systemd; If not, see <http://www.gnu.org/licenses/>.
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering***/
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt#include <assert.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <dirent.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <errno.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <fcntl.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <unistd.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <string.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <signal.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/socket.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/un.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/prctl.h>
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt#include <linux/sched.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/types.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/stat.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <grp.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <pwd.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <sys/mount.h>
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt#include <linux/fs.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <linux/oom.h>
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#ifdef HAVE_PAM
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include <security/pam_appl.h>
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt#endif
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "execute.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "strv.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "macro.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "util.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "log.h"
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt#include "ioprio.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "securebits.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "cgroup.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "namespace.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "tcpwrap.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "exit-status.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "missing.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#include "utmp-wtmp.h"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering/* This assumes there is a 'tty' group */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering#define TTY_MODE 0620
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int shift_fds(int fds[], unsigned n_fds) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int start, restart_from;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (n_fds <= 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Modifies the fds array! (sorts it) */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(fds);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering start = 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering for (;;) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int i;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering restart_from = -1;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
b97610038a122ff30e60b1996369ca4b979d8b19Kay Sievers for (i = start; i < (int) n_fds; i++) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int nfd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Already at right index? */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (fds[i] == i+3)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering continue;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering close_nointr_nofail(fds[i]);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt fds[i] = nfd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Hmm, the fd we wanted isn't free? Then
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt * let's remember that and try again from here*/
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt if (nfd != i+3 && restart_from < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering restart_from = i;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (restart_from < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering break;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering start = restart_from;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering unsigned i;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (n_fds <= 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(fds);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering for (i = 0; i < n_fds; i++) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if ((r = fd_nonblock(fds[i], nonblock)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* We unconditionally drop FD_CLOEXEC from the fds,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * since after all we want to pass these fds to our
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * children */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if ((r = fd_cloexec(fds[i], false)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic const char *tty_path(const ExecContext *context) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(context);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (context->tty_path)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return context->tty_path;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return "/dev/console";
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int open_null_as(int flags, int nfd) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int fd, r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(nfd >= 0);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
b97610038a122ff30e60b1996369ca4b979d8b19Kay Sievers if ((fd = open("/dev/null", flags|O_NOCTTY)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
270f1624022039b370b9db311f9d33492833ad24Lennart Poettering if (fd != nfd) {
270f1624022039b370b9db311f9d33492833ad24Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
270f1624022039b370b9db311f9d33492833ad24Lennart Poettering close_nointr_nofail(fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering } else
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt r = nfd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, int nfd) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int fd, r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering union {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering struct sockaddr sa;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering struct sockaddr_un un;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering } sa;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(context);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(output < _EXEC_OUTPUT_MAX);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(ident);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(nfd >= 0);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering zero(sa);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering sa.sa.sa_family = AF_UNIX;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering strncpy(sa.un.sun_path+1, LOGGER_SOCKET, sizeof(sa.un.sun_path)-1);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + 1 + sizeof(LOGGER_SOCKET) - 1) < 0) {
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt close_nointr_nofail(fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (shutdown(fd, SHUT_RD) < 0) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering close_nointr_nofail(fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* We speak a very simple protocol between log server
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt * and client: one line for the log destination (kmsg
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * or syslog), followed by the priority field,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * followed by the process name. Since we replaced
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * stdin/stderr we simple use stdio to write to
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * it. Note that we use stderr, to minimize buffer
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering * flushing issues. */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering dprintf(fd,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering "%s\n"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering "%i\n"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering "%s\n"
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering "%i\n",
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering output == EXEC_OUTPUT_KMSG ? "kmsg" :
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering output == EXEC_OUTPUT_KMSG_AND_CONSOLE ? "kmsg+console" :
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering output == EXEC_OUTPUT_SYSLOG ? "syslog" :
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering "syslog+console",
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering context->syslog_priority,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering context->syslog_identifier ? context->syslog_identifier : ident,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering context->syslog_level_prefix);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (fd != nfd) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering close_nointr_nofail(fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering } else
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering r = nfd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int open_terminal_as(const char *path, mode_t mode, int nfd) {
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt int fd, r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(path);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt assert(nfd >= 0);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt return fd;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (fd != nfd) {
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt r = dup2(fd, nfd) < 0 ? -errno : nfd;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt close_nointr_nofail(fd);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt } else
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering r = nfd;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic bool is_terminal_input(ExecInput i) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i == EXEC_INPUT_TTY ||
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt i == EXEC_INPUT_TTY_FORCE ||
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i == EXEC_INPUT_TTY_FAIL;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardtstatic int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (is_terminal_input(std_input) && !apply_tty_stdin)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return EXEC_INPUT_NULL;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return EXEC_INPUT_NULL;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return std_input;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int fixup_output(ExecOutput std_output, int socket_fd) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt return EXEC_OUTPUT_INHERIT;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return std_output;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt ExecInput i;
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt assert(context);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt switch (i) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_INPUT_NULL:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_null_as(O_RDONLY, STDIN_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt case EXEC_INPUT_TTY:
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt case EXEC_INPUT_TTY_FORCE:
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt case EXEC_INPUT_TTY_FAIL: {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int fd, r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt if ((fd = acquire_terminal(
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering tty_path(context),
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i == EXEC_INPUT_TTY_FAIL,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i == EXEC_INPUT_TTY_FORCE,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering false)) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return fd;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (fd != STDIN_FILENO) {
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering close_nointr_nofail(fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering } else
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering r = STDIN_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_INPUT_SOCKET:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt default:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert_not_reached("Unknown input type");
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int setup_output(const ExecContext *context, int socket_fd, const char *ident, bool apply_tty_stdin) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering ExecOutput o;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering ExecInput i;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(context);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(ident);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering o = fixup_output(context->std_output, socket_fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* This expects the input is already set up */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering switch (o) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_INHERIT:
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* If input got downgraded, inherit the original value */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt /* If the input is connected to anything that's not a /dev/null, inherit that... */
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt if (i != EXEC_INPUT_NULL)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (getppid() != 1)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return STDOUT_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* We need to open /dev/null here anew, to get the
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt * right access mode. So we fall through */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_NULL:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_null_as(O_WRONLY, STDOUT_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_TTY:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (is_terminal_input(i))
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* We don't reset the terminal if this is just about output */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
b97610038a122ff30e60b1996369ca4b979d8b19Kay Sievers
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_SYSLOG:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_KMSG:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_KMSG_AND_CONSOLE:
b97610038a122ff30e60b1996369ca4b979d8b19Kay Sievers return connect_logger_as(context, o, ident, STDOUT_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_SOCKET:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(socket_fd >= 0);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(socket_fd, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering default:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert_not_reached("Unknown output type");
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int setup_error(const ExecContext *context, int socket_fd, const char *ident, bool apply_tty_stdin) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering ExecOutput o, e;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering ExecInput i;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(context);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(ident);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering o = fixup_output(context->std_output, socket_fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering e = fixup_output(context->std_error, socket_fd);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* This expects the input and output are already set up */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Don't change the stderr file descriptor if we inherit all
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt * the way and are not on a tty */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (e == EXEC_OUTPUT_INHERIT &&
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering o == EXEC_OUTPUT_INHERIT &&
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt i == EXEC_INPUT_NULL &&
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering !is_terminal_input(context->std_input) &&
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering getppid () != 1)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return STDERR_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* Duplicate from stdout if possible */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (e == o || e == EXEC_OUTPUT_INHERIT)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(STDOUT_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering switch (e) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_NULL:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_null_as(O_WRONLY, STDERR_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt case EXEC_OUTPUT_TTY:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (is_terminal_input(i))
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return dup2(STDIN_FILENO, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* We don't reset the terminal if this is just about output */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_SYSLOG:
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_KMSG:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_KMSG_AND_CONSOLE:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return connect_logger_as(context, e, ident, STDERR_FILENO);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering case EXEC_OUTPUT_SOCKET:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(socket_fd >= 0);
4c2413bffa7861bd3c4b3589c821ab7e0ac51c83Jan Engelhardt return dup2(socket_fd, STDERR_FILENO) < 0 ? -errno : STDERR_FILENO;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering default:
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert_not_reached("Unknown error type");
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering }
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int chown_terminal(int fd, uid_t uid) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering struct stat st;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(fd >= 0);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering /* This might fail. What matters are the results. */
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering (void) fchown(fd, uid, -1);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering (void) fchmod(fd, TTY_MODE);
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (fstat(fd, &st) < 0)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -errno;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return -EPERM;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering return 0;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering}
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poetteringstatic int setup_confirm_stdio(const ExecContext *context,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int *_saved_stdin,
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int *_saved_stdout) {
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering int fd = -1, saved_stdin, saved_stdout = -1, r;
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering
e49b5aada0df13c9e8fce7338ae34e075dd7ccd1Lennart Poettering assert(context);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(_saved_stdin);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(_saved_stdout);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering /* This returns positive EXIT_xxx return values instead of
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering * negative errno style values! */
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if ((saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3)) < 0)
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering return EXIT_STDIN;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if ((saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3)) < 0) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering r = EXIT_STDOUT;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering goto fail;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering }
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if ((fd = acquire_terminal(
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering tty_path(context),
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering context->std_input == EXEC_INPUT_TTY_FAIL,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering context->std_input == EXEC_INPUT_TTY_FORCE,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering false)) < 0) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering r = EXIT_STDIN;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering goto fail;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering }
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (chown_terminal(fd, getuid()) < 0) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering r = EXIT_STDIN;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering goto fail;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering }
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (dup2(fd, STDIN_FILENO) < 0) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering r = EXIT_STDIN;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering goto fail;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering }
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (dup2(fd, STDOUT_FILENO) < 0) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering r = EXIT_STDOUT;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering goto fail;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering }
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (fd >= 2)
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering close_nointr_nofail(fd);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering *_saved_stdin = saved_stdin;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering *_saved_stdout = saved_stdout;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering return 0;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poetteringfail:
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (saved_stdout >= 0)
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering close_nointr_nofail(saved_stdout);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (saved_stdin >= 0)
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering close_nointr_nofail(saved_stdin);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (fd >= 0)
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering close_nointr_nofail(fd);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering return r;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering}
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poetteringstatic int restore_confirm_stdio(const ExecContext *context,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering int *saved_stdin,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering int *saved_stdout,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering bool *keep_stdin,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering bool *keep_stdout) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(context);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(saved_stdin);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(*saved_stdin >= 0);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(saved_stdout);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering assert(*saved_stdout >= 0);
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering /* This returns positive EXIT_xxx return values instead of
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering * negative errno style values! */
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering if (is_terminal_input(context->std_input)) {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering /* The service wants terminal input. */
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering *keep_stdin = true;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering *keep_stdout =
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering context->std_output == EXEC_OUTPUT_INHERIT ||
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering context->std_output == EXEC_OUTPUT_TTY;
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering } else {
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering /* If the service doesn't want a controlling terminal,
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering * then we need to get rid entirely of what we have
cd4010b37349413db1e553e213e62e654ca28113Lennart Poettering * already. */
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (release_terminal() < 0)
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return EXIT_STDIN;
f3a165b05d117b9a9657076fed6b265eb40d5ba3Kay Sievers
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (dup2(*saved_stdin, STDIN_FILENO) < 0)
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return EXIT_STDIN;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return EXIT_STDOUT;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *keep_stdout = *keep_stdin = false;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering }
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering}
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poetteringstatic int get_group_creds(const char *groupname, gid_t *gid) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering struct group *g;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering unsigned long lu;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(groupname);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(gid);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering /* We enforce some special rules for gid=0: in order to avoid
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * NSS lookups for root we hardcode its data. */
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (streq(groupname, "root") || streq(groupname, "0")) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *gid = 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering }
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
f3a165b05d117b9a9657076fed6b265eb40d5ba3Kay Sievers if (safe_atolu(groupname, &lu) >= 0) {
f3a165b05d117b9a9657076fed6b265eb40d5ba3Kay Sievers errno = 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering g = getgrgid((gid_t) lu);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering } else {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering errno = 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering g = getgrnam(groupname);
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering }
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (!g)
f3a165b05d117b9a9657076fed6b265eb40d5ba3Kay Sievers return errno != 0 ? -errno : -ESRCH;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *gid = g->gr_gid;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering}
f3a165b05d117b9a9657076fed6b265eb40d5ba3Kay Sievers
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poetteringstatic int get_user_creds(const char **username, uid_t *uid, gid_t *gid, const char **home) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering struct passwd *p;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering unsigned long lu;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(username);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(*username);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(uid);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(gid);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(home);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering /* We enforce some special rules for uid=0: in order to avoid
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * NSS lookups for root we hardcode its data. */
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (streq(*username, "root") || streq(*username, "0")) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *username = "root";
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *uid = 0;
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering *gid = 0;
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering *home = "/root";
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering return 0;
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering }
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering if (safe_atolu(*username, &lu) >= 0) {
387abf80ad40e4a6c2f4725c8eff4d66bf110d1fLennart Poettering errno = 0;
04bf3c1a60d82791e0320381e9268f727708f776Kay Sievers p = getpwuid((uid_t) lu);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering /* If there are multiple users with the same id, make
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * sure to leave $USER to the configured value instead
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * of the first occurrence in the database. However if
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * the uid was configured by a numeric uid, then let's
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * pick the real username from /etc/passwd. */
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (*username && p)
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *username = p->pw_name;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering } else {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering errno = 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering p = getpwnam(*username);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering }
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering if (!p)
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return errno != 0 ? -errno : -ESRCH;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *uid = p->pw_uid;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *gid = p->pw_gid;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering *home = p->pw_dir;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering return 0;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering}
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poetteringstatic int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering bool keep_groups = false;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering int r;
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering assert(context);
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering /* Lookup and set GID and supplementary group list. Here too
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering * we avoid NSS lookups for gid=0. */
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (context->group || username) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (context->group)
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if ((r = get_group_creds(context->group, &gid)) < 0)
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering return r;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering /* First step, initialize groups from /etc/groups */
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (username && gid != 0) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (initgroups(username, gid) < 0)
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering return -errno;
33b521be152f67cd722695ba9a2966eda5ee6765Maciej Wereski
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering keep_groups = true;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering /* Second step, set our gids */
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (setresgid(gid, gid, gid) < 0)
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering return -errno;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (context->supplementary_groups) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering int ngroups_max, k;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering gid_t *gids;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering char **i;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering /* Final step, initialize any manually set supplementary groups */
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering ngroups_max = (int) sysconf(_SC_NGROUPS_MAX);
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (!(gids = new(gid_t, ngroups_max)))
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering return -ENOMEM;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (keep_groups) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if ((k = getgroups(ngroups_max, gids)) < 0) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering free(gids);
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return -errno;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering }
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering } else
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering k = 0;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering STRV_FOREACH(i, context->supplementary_groups) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (k >= ngroups_max) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering free(gids);
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return -E2BIG;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering }
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if ((r = get_group_creds(*i, gids+k)) < 0) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering free(gids);
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return r;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering k++;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering if (setgroups(k, gids) < 0) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering free(gids);
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return -errno;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering free(gids);
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering }
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering return 0;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering}
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poetteringstatic int enforce_user(const ExecContext *context, uid_t uid) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering int r;
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering assert(context);
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering
28f5c779e5513ab1301ac103471009711b0961e0Kay Sievers /* Sets (but doesn't lookup) the uid and make sure we keep the
28f5c779e5513ab1301ac103471009711b0961e0Kay Sievers * capabilities while doing so. */
28f5c779e5513ab1301ac103471009711b0961e0Kay Sievers
28f5c779e5513ab1301ac103471009711b0961e0Kay Sievers if (context->capabilities) {
408f281bc7d65c86563f46e99e07efd1a1d9e03aLennart Poettering cap_t d;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering static const cap_value_t bits[] = {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering CAP_SETUID, /* Necessary so that we can run setresuid() below */
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering };
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering /* First step: If we need to keep capabilities but
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering * drop privileges we need to make sure we keep our
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering * caps, whiel we drop privileges. */
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (uid != 0) {
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering int sb = context->secure_bits|SECURE_KEEP_CAPS;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (prctl(PR_GET_SECUREBITS) != sb)
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (prctl(PR_SET_SECUREBITS, sb) < 0)
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return -errno;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering }
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering /* Second step: set the capabilities. This will reduce
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering * the capabilities to the minimum we need. */
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (!(d = cap_dup(context->capabilities)))
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering return -errno;
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering
251cc8194228ac86c9a7a4c75a54a94cea2095c7Lennart Poettering if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
4f0be680b5323e037314cfbd3dba34f03e637c8fLennart Poettering r = -errno;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering cap_free(d);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering return r;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (cap_set_proc(d) < 0) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering r = -errno;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering cap_free(d);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering return r;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering cap_free(d);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Third step: actually set the uids */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (setresuid(uid, uid, uid) < 0)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering return -errno;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* At this point we should have all necessary capabilities but
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering are otherwise a normal user. However, the caps might got
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering corrupted due to the setresuid() so we need clean them up
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering later. This is done outside of this call. */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering return 0;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering}
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering#ifdef HAVE_PAM
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poetteringstatic int null_conv(
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering int num_msg,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering const struct pam_message **msg,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering struct pam_response **resp,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering void *appdata_ptr) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* We don't support conversations */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering return PAM_CONV_ERR;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering}
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poetteringstatic int setup_pam(
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering const char *name,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering const char *user,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering const char *tty,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering char ***pam_env,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering int fds[], unsigned n_fds) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering static const struct pam_conv conv = {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering .conv = null_conv,
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering .appdata_ptr = NULL
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering };
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering pam_handle_t *handle = NULL;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering sigset_t ss, old_ss;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering int pam_code = PAM_SUCCESS;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering char **e = NULL;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering bool close_session = false;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering pid_t pam_pid = 0, parent_pid;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering assert(name);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering assert(user);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering assert(pam_env);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* We set up PAM in the parent process, then fork. The child
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * will then stay around until killed via PR_GET_PDEATHSIG or
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * systemd via the cgroup logic. It will then remove the PAM
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * session again. The parent process will exec() the actual
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * daemon. We do things this way to ensure that the main PID
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * of the daemon is the one we initially fork()ed. */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_start(name, user, &conv, &handle)) != PAM_SUCCESS) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering handle = NULL;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (tty)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_set_item(handle, PAM_TTY, tty)) != PAM_SUCCESS)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_acct_mgmt(handle, PAM_SILENT)) != PAM_SUCCESS)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_open_session(handle, PAM_SILENT)) != PAM_SUCCESS)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek close_session = true;
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_setcred(handle, PAM_ESTABLISH_CRED | PAM_SILENT)) != PAM_SUCCESS)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((!(e = pam_getenvlist(handle)))) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering pam_code = PAM_BUF_ERR;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Block SIGTERM, so that we know that it won't get lost in
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * the child */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (sigemptyset(&ss) < 0 ||
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering sigaddset(&ss, SIGTERM) < 0 ||
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek parent_pid = getpid();
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek
1fda0ab5fc9cf7454c8da32941e433dc38ba9991Zbigniew Jędrzejewski-Szmek if ((pam_pid = fork()) < 0)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto fail;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (pam_pid == 0) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering int sig;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering int r = EXIT_PAM;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* The child's job is to reset the PAM session on
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * termination */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* This string must fit in 10 chars (i.e. the length
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * of "/sbin/init") */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering rename_process("sd:pam");
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Make sure we don't keep open the passed fds in this
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering child. We assume that otherwise only those fds are
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering open here that have been opened by PAM. */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering close_many(fds, n_fds);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Wait until our parent died. This will most likely
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * not work since the kernel does not allow
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * unprivileged parents kill their privileged children
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * this way. We rely on the control groups kill logic
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * to do the rest for us. */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto child_finish;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Check if our parent process might already have
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering * died? */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (getppid() == parent_pid) {
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (sigwait(&ss, &sig) < 0)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering goto child_finish;
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering assert(sig == SIGTERM);
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering }
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering /* Only if our parent died we'll end the session */
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if (getppid() != parent_pid)
00aa832b948a27507c33e2157e46963852cffc85Lennart Poettering if ((pam_code = pam_close_session(handle, PAM_DATA_SILENT)) != PAM_SUCCESS)
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering goto child_finish;
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering r = 0;
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering child_finish:
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering pam_end(handle, pam_code | PAM_DATA_SILENT);
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering _exit(r);
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering }
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering /* If the child was forked off successfully it will do all the
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering * cleanups, so forget about the handle here. */
606c24e3bd41207c395f24a56bcfcad791e265a5Lennart Poettering handle = NULL;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering /* Unblock SIGSUR1 again in the parent */
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering goto fail;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering /* We close the log explicitly here, since the PAM modules
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering * might have opened it, but we don't want this fd around. */
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering closelog();
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return 0;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
b82eed9af95668ab38cac33c7996e4d665f8709aLennart Poetteringfail:
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (handle) {
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (close_session)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering pam_code = pam_close_session(handle, PAM_DATA_SILENT);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering pam_end(handle, pam_code | PAM_DATA_SILENT);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering }
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering strv_free(e);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering closelog();
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (pam_pid > 1)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering kill(pam_pid, SIGTERM);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return EXIT_PAM;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering}
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering#endif
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poetteringint exec_spawn(ExecCommand *command,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering char **argv,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering const ExecContext *context,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering int fds[], unsigned n_fds,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering char **environment,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering bool apply_permissions,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering bool apply_chroot,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering bool apply_tty_stdin,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering bool confirm_spawn,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering CGroupBonding *cgroup_bondings,
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering pid_t *ret) {
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering pid_t pid;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering int r;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering char *line;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering int socket_fd;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering assert(command);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering assert(context);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering assert(ret);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering assert(fds || n_fds <= 0);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (context->std_input == EXEC_INPUT_SOCKET ||
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering context->std_output == EXEC_OUTPUT_SOCKET ||
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering context->std_error == EXEC_OUTPUT_SOCKET) {
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (n_fds != 1)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return -EINVAL;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering socket_fd = fds[0];
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering fds = NULL;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering n_fds = 0;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering } else
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering socket_fd = -1;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (!argv)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering argv = command->argv;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (!(line = exec_command_line(argv)))
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return -ENOMEM;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering log_debug("About to execute: %s", line);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering free(line);
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if (cgroup_bondings)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if ((r = cgroup_bonding_realize_list(cgroup_bondings)))
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return r;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering if ((pid = fork()) < 0)
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering return -errno;
2f3fcf85c5fa6c9c483b31823a0efdd28914c756Lennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (pid == 0) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering int i;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering sigset_t ss;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering const char *username = NULL, *home = NULL;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering uid_t uid = (uid_t) -1;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering gid_t gid = (gid_t) -1;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering unsigned n_env = 0;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering int saved_stdout = -1, saved_stdin = -1;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering bool keep_stdout = false, keep_stdin = false;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* child */
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* This string must fit in 10 chars (i.e. the length
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * of "/sbin/init") */
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering rename_process("sd:exec");
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* We reset exactly these signals, since they are the
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * only ones we set to SIG_IGN in the main daemon. All
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * others we leave untouched because we set them to
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * SIG_DFL or a valid handler initially, both of which
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * will be demoted to SIG_DFL. */
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering default_signals(SIGNALS_CRASH_HANDLER,
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering SIGNALS_IGNORE, -1);
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (sigemptyset(&ss) < 0 ||
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering r = EXIT_SIGNAL_MASK;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering goto fail;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering }
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* Close sockets very early to make sure we don't
7c04ad2da1cf08ebf53b9aa9671c8c1dc9577135Lennart Poettering * block init reexecution because it cannot bind its
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering * sockets */
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (close_all_fds(socket_fd >= 0 ? &socket_fd : fds,
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering socket_fd >= 0 ? 1 : n_fds) < 0) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering r = EXIT_FDS;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering goto fail;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering }
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (!context->same_pgrp)
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (setsid() < 0) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering r = EXIT_SETSID;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering goto fail;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering }
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (context->tcpwrap_name) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (socket_fd >= 0)
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
7c04ad2da1cf08ebf53b9aa9671c8c1dc9577135Lennart Poettering r = EXIT_TCPWRAP;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering goto fail;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering }
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek for (i = 0; i < (int) n_fds; i++) {
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek r = EXIT_TCPWRAP;
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek goto fail;
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek }
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek }
cbeabcfbc5a5fa27385e5794780e8f034e090606Zbigniew Jędrzejewski-Szmek }
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* We skip the confirmation step if we shall not apply the TTY */
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering if (confirm_spawn &&
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering (!is_terminal_input(context->std_input) || apply_tty_stdin)) {
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering char response;
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering
ef3b5246879094e29cc99c4d24cbfeb19b7da49bLennart Poettering /* Set up terminal for the question */
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if ((r = setup_confirm_stdio(context,
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering &saved_stdin, &saved_stdout)))
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering /* Now ask the question. */
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (!(line = exec_command_line(argv))) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_MEMORY;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = ask(&response, "yns", "Execute %s? [Yes, No, Skip] ", line);
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering free(line);
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (r < 0 || response == 'n') {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_CONFIRM;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering } else if (response == 's') {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = 0;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering /* Release terminal for the question */
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if ((r = restore_confirm_stdio(context,
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering &saved_stdin, &saved_stdout,
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering &keep_stdin, &keep_stdout)))
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering /* If a socket is connected to STDIN/STDOUT/STDERR, we
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering * must sure to drop O_NONBLOCK */
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (socket_fd >= 0)
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering fd_nonblock(socket_fd, false);
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (!keep_stdin)
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (setup_input(context, socket_fd, apply_tty_stdin) < 0) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_STDIN;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (!keep_stdout)
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (setup_output(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_STDOUT;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (setup_error(context, socket_fd, file_name_from_path(command->path), apply_tty_stdin) < 0) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_STDERR;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (cgroup_bondings)
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (cgroup_bonding_install_list(cgroup_bondings, 0) < 0) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering r = EXIT_CGROUP;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering goto fail;
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering }
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (context->oom_score_adjust_set) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering char t[16];
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering char_array_0(t);
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering if (write_one_line_file("/proc/self/oom_score_adj", t) < 0) {
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering /* Compatibility with Linux <= 2.6.35 */
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering
d3a86981d1ae4c1d668e18868c3e6c9d2f23c144Lennart Poettering int adj;
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering adj = (context->oom_score_adjust * -OOM_DISABLE) / OOM_SCORE_ADJ_MAX;
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering adj = CLAMP(adj, OOM_DISABLE, OOM_ADJUST_MAX);
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering snprintf(t, sizeof(t), "%i", adj);
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering char_array_0(t);
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering if (write_one_line_file("/proc/self/oom_adj", t) < 0) {
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering r = EXIT_OOM_ADJUST;
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering goto fail;
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering }
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering }
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering }
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering if (context->nice_set)
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
9ca3c17f207121b3c19a44217558b056a7585944Lennart Poettering r = EXIT_NICE;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (context->cpu_sched_set) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering struct sched_param param;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering zero(param);
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering param.sched_priority = context->cpu_sched_priority;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (sched_setscheduler(0, context->cpu_sched_policy |
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering (context->cpu_sched_reset_on_fork ? SCHED_RESET_ON_FORK : 0), &param) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_SETSCHEDULER;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (context->cpuset)
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_CPUAFFINITY;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (context->ioprio_set)
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_IOPRIO;
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (context->timer_slack_nsec_set)
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_TIMERSLACK;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
c20d8298029a39cc3e9602b30a4d23b951e11df8Kay Sievers }
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek if (context->utmp_id)
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek utmp_put_init_process(0, context->utmp_id, getpid(), getsid(0), context->tty_path);
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (context->user) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering username = context->user;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (get_user_creds(&username, &uid, &gid, &home) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_USER;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (is_terminal_input(context->std_input))
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (chown_terminal(STDIN_FILENO, uid) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_STDIN;
6a7d3d68bf1ae9bcdaa3a17bc76f72bb7b988ec4Lennart Poettering goto fail;
6a7d3d68bf1ae9bcdaa3a17bc76f72bb7b988ec4Lennart Poettering }
6a7d3d68bf1ae9bcdaa3a17bc76f72bb7b988ec4Lennart Poettering }
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek
a87197f5a22688626dc9bead29ddc1c572b074b9Zbigniew Jędrzejewski-Szmek#ifdef HAVE_PAM
c20d8298029a39cc3e9602b30a4d23b951e11df8Kay Sievers if (context->pam_name && username) {
ab06eef8101866dd1337c4759002f7360a9db416Anatol Pomozov if (setup_pam(context->pam_name, username, context->tty_path, &pam_env, fds, n_fds) < 0) {
c20d8298029a39cc3e9602b30a4d23b951e11df8Kay Sievers r = EXIT_PAM;
c20d8298029a39cc3e9602b30a4d23b951e11df8Kay Sievers goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering#endif
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (apply_permissions)
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering if (enforce_groups(context, username, uid) < 0) {
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering r = EXIT_GROUP;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering goto fail;
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering }
35911459410714a0e9108b35da78f96919b65ee7Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering umask(context->umask);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (strv_length(context->read_write_dirs) > 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_length(context->read_only_dirs) > 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_length(context->inaccessible_dirs) > 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->mount_flags != MS_SHARED ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->private_tmp)
ad88e758d1b08a21d25971b074e119c167757109Zbigniew Jędrzejewski-Szmek if ((r = setup_namespace(
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->read_write_dirs,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->read_only_dirs,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->inaccessible_dirs,
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers context->private_tmp,
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers context->mount_flags)) < 0)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (apply_chroot) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (context->root_directory)
fd86897568f7a1aed7ffe4c54ace6c158ddbdf7dKay Sievers if (chroot(context->root_directory) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_CHROOT;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_CHDIR;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering } else {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
156f7d09add8fc93cae8a3f13adcb2564931fee4Kay Sievers char *d;
156f7d09add8fc93cae8a3f13adcb2564931fee4Kay Sievers
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (asprintf(&d, "%s/%s",
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->root_directory ? context->root_directory : "",
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->working_directory ? context->working_directory : "") < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_MEMORY;
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (chdir(d) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(d);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_CHDIR;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(d);
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering /* We repeat the fd closing here, to make sure that
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering * nothing is leaked from the PAM modules */
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (close_all_fds(fds, n_fds) < 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering shift_fds(fds, n_fds) < 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering flags_fds(fds, n_fds, context->non_blocking) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_FDS;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering goto fail;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (apply_permissions) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering for (i = 0; i < RLIMIT_NLIMITS; i++) {
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (!context->rlimit[i])
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering continue;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (setrlimit(i, context->rlimit[i]) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_LIMITS;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering }
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering }
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (context->user)
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (enforce_user(context, uid) < 0) {
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering r = EXIT_USER;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering /* PR_GET_SECUREBITS is not privileged, while
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * PR_SET_SECUREBITS is. So to suppress
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * potential EPERMs we'll try not to call
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * PR_SET_SECUREBITS unless necessary. */
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_SECUREBITS;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (context->capabilities)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (cap_set_proc(context->capabilities) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_CAPABILITIES;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (!(our_env = new0(char*, 7))) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (n_fds > 0)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (asprintf(our_env + n_env++, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0 ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering asprintf(our_env + n_env++, "LISTEN_FDS=%u", n_fds) < 0) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (home)
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers if (asprintf(our_env + n_env++, "HOME=%s", home) < 0) {
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (username)
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (asprintf(our_env + n_env++, "LOGNAME=%s", username) < 0 ||
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering asprintf(our_env + n_env++, "USER=%s", username) < 0) {
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering r = EXIT_MEMORY;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (is_terminal_input(context->std_input) ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->std_output == EXEC_OUTPUT_TTY ||
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering context->std_error == EXEC_OUTPUT_TTY)
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering if (!(our_env[n_env++] = strdup(default_term_for_tty(tty_path(context))))) {
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering assert(n_env <= 7);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (!(final_env = strv_env_merge(
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering 4,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering environment,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering our_env,
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers context->environment,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering pam_env,
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering NULL))) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (!(final_argv = replace_env_argv(argv, final_env))) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_MEMORY;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering goto fail;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
bf9335608821264163058a8b036a00775a8ffbe4Kay Sievers
bf9335608821264163058a8b036a00775a8ffbe4Kay Sievers final_env = strv_env_clean(final_env);
bf9335608821264163058a8b036a00775a8ffbe4Kay Sievers
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering execve(command->path, final_argv, final_env);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering r = EXIT_EXEC;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering fail:
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(our_env);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(final_env);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(pam_env);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(final_argv);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (saved_stdin >= 0)
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers close_nointr_nofail(saved_stdin);
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (saved_stdout >= 0)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering close_nointr_nofail(saved_stdout);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering _exit(r);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering /* We add the new process to the cgroup both in the child (so
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * that we can be sure that no user code is ever executed
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * outside of the cgroup) and in the parent (so that we can be
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * sure that when we kill the cgroup the process will be
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering * killed too). */
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (cgroup_bondings)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering cgroup_bonding_install_list(cgroup_bondings, pid);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering log_debug("Forked %s as %lu", command->path, (unsigned long) pid);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering exec_status_start(&command->exec_status, pid);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering *ret = pid;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering return 0;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering}
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poetteringvoid exec_context_init(ExecContext *c) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering assert(c);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->umask = 0002;
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->cpu_sched_policy = SCHED_OTHER;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->syslog_priority = LOG_DAEMON|LOG_INFO;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->syslog_level_prefix = true;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->mount_flags = MS_SHARED;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->kill_signal = SIGTERM;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->send_sigkill = true;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering}
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poetteringvoid exec_context_done(ExecContext *c) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering unsigned l;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering assert(c);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->environment);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->environment = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->rlimit[l]);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->rlimit[l] = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
43447fb72693d62363a1a271dacc70d400ed685bLennart Poettering free(c->working_directory);
43447fb72693d62363a1a271dacc70d400ed685bLennart Poettering c->working_directory = NULL;
43447fb72693d62363a1a271dacc70d400ed685bLennart Poettering free(c->root_directory);
43447fb72693d62363a1a271dacc70d400ed685bLennart Poettering c->root_directory = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->tty_path);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->tty_path = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->tcpwrap_name);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->tcpwrap_name = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->syslog_identifier);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->syslog_identifier = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->user);
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering c->user = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->group);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->group = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->supplementary_groups);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->supplementary_groups = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
6aa8d43ade72e24c9426e604f7fc4b7582b9db7cLennart Poettering free(c->pam_name);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->pam_name = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering if (c->capabilities) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering cap_free(c->capabilities);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->capabilities = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering }
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->read_only_dirs);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->read_only_dirs = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->read_write_dirs);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->read_write_dirs = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->inaccessible_dirs);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->inaccessible_dirs = NULL;
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers
40e21da873c120936faff0aa42a6533f6933edf7Kay Sievers if (c->cpuset)
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering CPU_FREE(c->cpuset);
1aed45907715ad4dce7dbc84a957cd5de8cca36eLennart Poettering
1aed45907715ad4dce7dbc84a957cd5de8cca36eLennart Poettering free(c->utmp_id);
1aed45907715ad4dce7dbc84a957cd5de8cca36eLennart Poettering c->utmp_id = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering}
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poetteringvoid exec_command_done(ExecCommand *c) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering assert(c);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering free(c->path);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->path = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering strv_free(c->argv);
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering c->argv = NULL;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering}
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poetteringvoid exec_command_done_array(ExecCommand *c, unsigned n) {
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering unsigned i;
85d683970b7dc2c4470b2b7d60c3d9dce28c1471Lennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering for (i = 0; i < n; i++)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering exec_command_done(c+i);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering}
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poetteringvoid exec_command_free_list(ExecCommand *c) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering ExecCommand *i;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering while ((i = c)) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering LIST_REMOVE(ExecCommand, command, c, i);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering exec_command_done(i);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering free(i);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering }
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering}
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poetteringvoid exec_command_free_array(ExecCommand **c, unsigned n) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering unsigned i;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering for (i = 0; i < n; i++) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering exec_command_free_list(c[i]);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering c[i] = NULL;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering }
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering}
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poetteringstatic void strv_fprintf(FILE *f, char **l) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering char **g;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering assert(f);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering STRV_FOREACH(g, l)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, " %s", *g);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering}
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poetteringvoid exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering char ** e;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering unsigned i;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering assert(c);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering assert(f);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (!prefix)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix = "";
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sUMask: %04o\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sWorkingDirectory: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sRootDirectory: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sNonBlocking: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sPrivateTmp: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->umask,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->working_directory ? c->working_directory : "/",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->root_directory ? c->root_directory : "/",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, yes_no(c->non_blocking),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, yes_no(c->private_tmp));
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->environment)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering for (e = c->environment; *e; e++)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%sEnvironment: %s\n", prefix, *e);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->tcpwrap_name)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sTCPWrapName: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->tcpwrap_name);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->nice_set)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sNice: %i\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->nice);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->oom_score_adjust_set)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sOOMScoreAdjust: %i\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->oom_score_adjust);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering for (i = 0; i < RLIM_NLIMITS; i++)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->rlimit[i])
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->ioprio_set)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sIOSchedulingClass: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sIOPriority: %i\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, ioprio_class_to_string(IOPRIO_PRIO_CLASS(c->ioprio)),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->cpu_sched_set)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sCPUSchedulingPolicy: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sCPUSchedulingPriority: %i\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sCPUSchedulingResetOnFork: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, sched_policy_to_string(c->cpu_sched_policy),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->cpu_sched_priority,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, yes_no(c->cpu_sched_reset_on_fork));
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->cpuset) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%sCPUAffinity:", prefix);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering for (i = 0; i < c->cpuset_ncpus; i++)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, " %i", i);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fputs("\n", f);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering }
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->timer_slack_nsec_set)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, c->timer_slack_nsec);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sStandardInput: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sStandardOutput: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sStandardError: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, exec_input_to_string(c->std_input),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, exec_output_to_string(c->std_output),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, exec_output_to_string(c->std_error));
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->tty_path)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sTTYPath: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, c->tty_path);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG ||
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG ||
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f,
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sSyslogFacility: %s\n"
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering "%sSyslogLevel: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, log_facility_to_string(LOG_FAC(c->syslog_priority)),
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, log_level_to_string(LOG_PRI(c->syslog_priority)));
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->capabilities) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering char *t;
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if ((t = cap_to_text(c->capabilities, NULL))) {
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%sCapabilities: %s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix, t);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering cap_free(t);
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering }
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering }
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering if (c->secure_bits)
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
8ad2685909f988602eca32ccba5c8ea4159e7f2eLennart Poettering prefix,
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_KEEP_CAPS) ? " keep-caps" : "",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_NOROOT) ? " noroot" : "",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering (c->secure_bits & SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->capability_bounding_set_drop) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sCapabilityBoundingSetDrop:", prefix);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
96ec33c079caacdf9c7cdfb2cad2f1bc48dfca65Lennart Poettering for (i = 0; i <= CAP_LAST_CAP; i++)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->capability_bounding_set_drop & (1 << i)) {
96ec33c079caacdf9c7cdfb2cad2f1bc48dfca65Lennart Poettering char *t;
96ec33c079caacdf9c7cdfb2cad2f1bc48dfca65Lennart Poettering
96ec33c079caacdf9c7cdfb2cad2f1bc48dfca65Lennart Poettering if ((t = cap_to_name(i))) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, " %s", t);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering free(t);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fputs("\n", f);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->user)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sUser: %s\n", prefix, c->user);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->group)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sGroup: %s\n", prefix, c->group);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (strv_length(c->supplementary_groups) > 0) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sSupplementaryGroups:", prefix);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering strv_fprintf(f, c->supplementary_groups);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fputs("\n", f);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->pam_name)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (strv_length(c->read_write_dirs) > 0) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sReadWriteDirs:", prefix);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering strv_fprintf(f, c->read_write_dirs);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fputs("\n", f);
ab06eef8101866dd1337c4759002f7360a9db416Anatol Pomozov }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (strv_length(c->read_only_dirs) > 0) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sReadOnlyDirs:", prefix);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering strv_fprintf(f, c->read_only_dirs);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fputs("\n", f);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (strv_length(c->inaccessible_dirs) > 0) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f, "%sInaccessibleDirs:", prefix);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering strv_fprintf(f, c->inaccessible_dirs);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fputs("\n", f);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering }
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f,
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sKillMode: %s\n"
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sKillSignal: SIG%s\n"
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sSendSIGKILL: %s\n",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, kill_mode_to_string(c->kill_mode),
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, signal_to_string(c->kill_signal),
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, yes_no(c->send_sigkill));
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (c->utmp_id)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f,
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sUtmpIdentifier: %s\n",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, c->utmp_id);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering}
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poetteringvoid exec_status_start(ExecStatus *s, pid_t pid) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering assert(s);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering zero(*s);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering s->pid = pid;
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering dual_timestamp_get(&s->start_timestamp);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering}
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poetteringvoid exec_status_exit(ExecStatus *s, pid_t pid, int code, int status, const char *utmp_id) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering assert(s);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if ((s->pid && s->pid != pid) ||
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering !s->start_timestamp.realtime <= 0)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering zero(*s);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering s->pid = pid;
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering dual_timestamp_get(&s->exit_timestamp);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering s->code = code;
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering s->status = status;
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (utmp_id)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering utmp_put_dead_process(utmp_id, pid, code, status);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering}
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poetteringvoid exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering char buf[FORMAT_TIMESTAMP_MAX];
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering assert(s);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering assert(f);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (!prefix)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix = "";
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (s->pid <= 0)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering return;
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f,
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sPID: %lu\n",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, (unsigned long) s->pid);
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering if (s->start_timestamp.realtime > 0)
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering fprintf(f,
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering "%sStart Timestamp: %s\n",
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
0428ddb729d12563b827510e04663de9cb4056f3Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (s->exit_timestamp.realtime > 0)
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering fprintf(f,
6827101ab4df4730a22062f4b3a8f8c2bae5be28Zbigniew Jędrzejewski-Szmek "%sExit Timestamp: %s\n"
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering "%sExit Code: %s\n"
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering "%sExit Status: %i\n",
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
6827101ab4df4730a22062f4b3a8f8c2bae5be28Zbigniew Jędrzejewski-Szmek prefix, sigchld_code_to_string(s->code),
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering prefix, s->status);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering}
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poetteringchar *exec_command_line(char **argv) {
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering size_t k;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering char *n, *p, **a;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering bool first = true;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering assert(argv);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering k = 1;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering STRV_FOREACH(a, argv)
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering k += strlen(*a)+3;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (!(n = new(char, k)))
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering return NULL;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering p = n;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering STRV_FOREACH(a, argv) {
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (!first)
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering *(p++) = ' ';
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering else
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering first = false;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (strpbrk(*a, WHITESPACE)) {
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering *(p++) = '\'';
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering p = stpcpy(p, *a);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering *(p++) = '\'';
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering } else
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering p = stpcpy(p, *a);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering }
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering *p = 0;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering /* FIXME: this doesn't really handle arguments that have
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering * spaces and ticks in them */
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering return n;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering}
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poetteringvoid exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering char *p2;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering const char *prefix2;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering char *cmd;
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering assert(c);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering assert(f);
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (!prefix)
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering prefix = "";
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering p2 = strappend(prefix, "\t");
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering prefix2 = p2 ? p2 : prefix;
15f47220ab59f480ddedc422cad435091778fc95Ben Boeckel
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering cmd = exec_command_line(c->argv);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering fprintf(f,
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering "%sCommand Line: %s\n",
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering prefix, cmd ? cmd : strerror(ENOMEM));
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering free(cmd);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering exec_status_dump(&c->exec_status, f, prefix2);
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering free(p2);
4d92e078e9d7e9a9d346065ea5e4afbafbdadb48Lennart Poettering}
4d92e078e9d7e9a9d346065ea5e4afbafbdadb48Lennart Poettering
4d92e078e9d7e9a9d346065ea5e4afbafbdadb48Lennart Poetteringvoid exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
4d92e078e9d7e9a9d346065ea5e4afbafbdadb48Lennart Poettering assert(f);
4d92e078e9d7e9a9d346065ea5e4afbafbdadb48Lennart Poettering
139ee8cc316a861bcc8a8ebdf4a8449dffe16f79Lennart Poettering if (!prefix)
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering prefix = "";
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering LIST_FOREACH(command, c, c)
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering exec_command_dump(c, f, prefix);
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering}
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poetteringvoid exec_command_append_list(ExecCommand **l, ExecCommand *e) {
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering ExecCommand *end;
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering assert(l);
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering assert(e);
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering if (*l) {
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering /* It's kind of important, that we keep the order here */
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering LIST_FIND_TAIL(ExecCommand, command, *l, end);
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering LIST_INSERT_AFTER(ExecCommand, command, *l, end, e);
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering } else
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering *l = e;
f9b557200b6d59a3dce1623d0873a259ee2fe421Lennart Poettering}
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poetteringint exec_command_set(ExecCommand *c, const char *path, ...) {
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering va_list ap;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering char **l, *p;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering assert(c);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering assert(path);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering va_start(ap, path);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering l = strv_new_ap(path, ap);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering va_end(ap);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering if (!l)
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering return -ENOMEM;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering if (!(p = strdup(path))) {
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering strv_free(l);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering return -ENOMEM;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering }
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering free(c->path);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering c->path = p;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering strv_free(c->argv);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering c->argv = l;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering return 0;
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering}
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poetteringstatic const char* const exec_input_table[_EXEC_INPUT_MAX] = {
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering [EXEC_INPUT_NULL] = "null",
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering [EXEC_INPUT_TTY] = "tty",
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering [EXEC_INPUT_TTY_FORCE] = "tty-force",
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering [EXEC_INPUT_TTY_FAIL] = "tty-fail",
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering [EXEC_INPUT_SOCKET] = "socket"
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering};
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poetteringstatic const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_INHERIT] = "inherit",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_NULL] = "null",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_TTY] = "tty",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_SYSLOG] = "syslog",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_KMSG] = "kmsg",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering [EXEC_OUTPUT_SOCKET] = "socket"
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering};
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poettering
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);
597c52cfedb5edd13ee1635fa6be72fc80e587c3Lennart Poettering
075d4ecb4026c5bc55e73bd2d44e3fc4d679adc7Lennart Poetteringstatic const char* const kill_mode_table[_KILL_MODE_MAX] = {
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_CONTROL_GROUP] = "control-group",
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_PROCESS_GROUP] = "process-group",
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_PROCESS] = "process",
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_NONE] = "none"
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering};
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(kill_mode, KillMode);
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poetteringstatic const char* const kill_who_table[_KILL_WHO_MAX] = {
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_MAIN] = "main",
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_CONTROL] = "control",
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering [KILL_ALL] = "all"
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering};
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart Poettering
b6a867398de9f75fb623a84db7c6181d26b0a8d5Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(kill_who, KillWho);
6563b535a062055ae68f2e574018d9d04a864b65Lennart Poettering