execute.c revision f146f5e159445c4fc7e89fe19ee2b8d72fc19ed7
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering/***
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering This file is part of systemd.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Copyright 2010 Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is free software; you can redistribute it and/or modify it
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering under the terms of the GNU Lesser General Public License as published by
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (at your option) any later version.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering systemd is distributed in the hope that it will be useful, but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering Lesser General Public License for more details.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering You should have received a copy of the GNU Lesser General Public License
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering***/
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <assert.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <dirent.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include <unistd.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <string.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include <signal.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/socket.h>
96aad8d15a324d0e956a4e5653a11a67b209b41aLennart Poettering#include <sys/un.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/prctl.h>
23c80348e656a4e6fd9ba8f17523a65b6fa349a0Kay Sievers#include <linux/sched.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/types.h>
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#include <sys/stat.h>
25300b5a1fcf54674a69d0f4ab08925be00b0227Lennart Poettering#include <grp.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <pwd.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <sys/mount.h>
003dffde2c1b93afbc9aff24b277276f65424406Lennart Poettering#include <linux/fs.h>
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering#include <linux/oom.h>
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering#include <sys/poll.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <linux/seccomp-bpf.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include <glob.h>
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering#include <libgen.h>
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#undef basename
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering
b1d4f8e154bf61b5de1b27461ef8e9c8c5e838a1Lennart Poettering#ifdef HAVE_PAM
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <security/pam_appl.h>
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#endif
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "execute.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "strv.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "macro.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "capability.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "util.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "log.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "sd-messages.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "ioprio.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "securebits.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "namespace.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "tcpwrap.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "exit-status.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "missing.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "utmp-wtmp.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "def.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "path-util.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "syscall-list.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "env-util.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "fileio.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "unit.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#include "async.h"
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering/* This assumes there is a 'tty' group */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define TTY_MODE 0620
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering#define SNDBUF_SIZE (8*1024*1024)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poetteringstatic int shift_fds(int fds[], unsigned n_fds) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int start, restart_from;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (n_fds <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Modifies the fds array! (sorts it) */
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
cb81cd8073392936882643af0129934bf67e96c4Lennart Poettering assert(fds);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering start = 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering for (;;) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int i;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering restart_from = -1;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering for (i = start; i < (int) n_fds; i++) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int nfd;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Already at right index? */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (fds[i] == i+3)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering continue;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return -errno;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering close_nointr_nofail(fds[i]);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering fds[i] = nfd;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Hmm, the fd we wanted isn't free? Then
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering * let's remember that and try again from here*/
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (nfd != i+3 && restart_from < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering restart_from = i;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (restart_from < 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering break;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering start = restart_from;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering }
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering}
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
cb81cd8073392936882643af0129934bf67e96c4Lennart Poetteringstatic int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering unsigned i;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering int r;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering if (n_fds <= 0)
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering return 0;
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering assert(fds);
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering for (i = 0; i < n_fds; i++) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((r = fd_nonblock(fds[i], nonblock)) < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* We unconditionally drop FD_CLOEXEC from the fds,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * since after all we want to pass these fds to our
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * children */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((r = fd_cloexec(fds[i], false)) < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return 0;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering_pure_ static const char *tty_path(const ExecContext *context) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(context);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (context->tty_path)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering return context->tty_path;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering return "/dev/console";
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringstatic void exec_context_tty_reset(const ExecContext *context) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering assert(context);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (context->tty_vhangup)
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering terminal_vhangup(tty_path(context));
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (context->tty_reset)
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering reset_terminal(tty_path(context));
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering if (context->tty_vt_disallocate && context->tty_path)
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering vt_disallocate(context->tty_path);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering}
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poetteringstatic bool is_terminal_output(ExecOutput o) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering return
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering o == EXEC_OUTPUT_TTY ||
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering}
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poetteringstatic int open_null_as(int flags, int nfd) {
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering int fd, r;
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering assert(nfd >= 0);
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering fd = open("/dev/null", flags|O_NOCTTY);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (fd < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering if (fd != nfd) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = nfd;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return r;
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int fd, r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering union sockaddr_union sa = {
06820eafdbc3dd89cb1f7563564c7d91426709caLennart Poettering .un.sun_family = AF_UNIX,
06820eafdbc3dd89cb1f7563564c7d91426709caLennart Poettering .un.sun_path = "/run/systemd/journal/stdout",
06820eafdbc3dd89cb1f7563564c7d91426709caLennart Poettering };
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering assert(context);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering assert(output < _EXEC_OUTPUT_MAX);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering assert(ident);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering assert(nfd >= 0);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering fd = socket(AF_UNIX, SOCK_STREAM, 0);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering if (fd < 0)
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering return -errno;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
4e724d9c5ab76c3f8327945317463ef706011082Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -errno;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
de0671ee7fe465e108f62dcbbbe9366f81dd9e9aZbigniew Jędrzejewski-Szmek if (shutdown(fd, SHUT_RD) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dprintf(fd,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "%s\n"
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering "%s\n"
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering "%i\n"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "%i\n"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "%i\n"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "%i\n"
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "%i\n",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->syslog_identifier ? context->syslog_identifier : ident,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unit_id,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->syslog_priority,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering !!context->syslog_level_prefix,
df2d202e6ed4001a21c6512c244acad5d4706c87Lennart Poettering output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering is_terminal_output(output));
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (fd != nfd) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = nfd;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int open_terminal_as(const char *path, mode_t mode, int nfd) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int fd, r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(path);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert(nfd >= 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return fd;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (fd != nfd) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = nfd;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
9030ca462bd13cd6536299814e4a71d5c5e85be9Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic bool is_terminal_input(ExecInput i) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return
8aec412ff697bc14995746953912ca6fdf2c9ba8Lennart Poettering i == EXEC_INPUT_TTY ||
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering i == EXEC_INPUT_TTY_FORCE ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i == EXEC_INPUT_TTY_FAIL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (is_terminal_input(std_input) && !apply_tty_stdin)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return EXEC_INPUT_NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return EXEC_INPUT_NULL;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return std_input;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poetteringstatic int fixup_output(ExecOutput std_output, int socket_fd) {
7f0d207d2c816e0a8cb2742b0a789911f7c99356Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return EXEC_OUTPUT_INHERIT;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return std_output;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ExecInput i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(context);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering switch (i) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_INPUT_NULL:
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return open_null_as(O_RDONLY, STDIN_FILENO);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering case EXEC_INPUT_TTY:
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering case EXEC_INPUT_TTY_FORCE:
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering case EXEC_INPUT_TTY_FAIL: {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering int fd, r;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering fd = acquire_terminal(tty_path(context),
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering i == EXEC_INPUT_TTY_FAIL,
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering i == EXEC_INPUT_TTY_FORCE,
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering false,
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering (usec_t) -1);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (fd < 0)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return fd;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd != STDIN_FILENO) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = STDIN_FILENO;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering case EXEC_INPUT_SOCKET:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering default:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_not_reached("Unknown input type");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering}
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poetteringstatic int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering ExecOutput o;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering ExecInput i;
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering int r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering assert(context);
5b12334d35eadf1f45cc3d631fd1a2e72ffaea0aLennart Poettering assert(ident);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering o = fixup_output(context->std_output, socket_fd);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fileno == STDERR_FILENO) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering ExecOutput e;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering e = fixup_output(context->std_error, socket_fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* This expects the input and output are already set up */
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Don't change the stderr file descriptor if we inherit all
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the way and are not on a tty */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (e == EXEC_OUTPUT_INHERIT &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o == EXEC_OUTPUT_INHERIT &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering i == EXEC_INPUT_NULL &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !is_terminal_input(context->std_input) &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering getppid () != 1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fileno;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Duplicate from stdout if possible */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (e == o || e == EXEC_OUTPUT_INHERIT)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o = e;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (o == EXEC_OUTPUT_INHERIT) {
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering /* If input got downgraded, inherit the original value */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If the input is connected to anything that's not a /dev/null, inherit that... */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (i != EXEC_INPUT_NULL)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering if (getppid() != 1)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return fileno;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* We need to open /dev/null here anew, to get the right access mode. */
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return open_null_as(O_WRONLY, fileno);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering switch (o) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case EXEC_OUTPUT_NULL:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return open_null_as(O_WRONLY, fileno);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case EXEC_OUTPUT_TTY:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (is_terminal_input(i))
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering /* We don't reset the terminal if this is just about output */
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, fileno);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case EXEC_OUTPUT_SYSLOG:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering case EXEC_OUTPUT_KMSG:
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering case EXEC_OUTPUT_KMSG_AND_CONSOLE:
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering case EXEC_OUTPUT_JOURNAL:
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = connect_logger_as(context, o, ident, unit_id, fileno);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering log_struct_unit(LOG_CRIT, unit_id,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering "MESSAGE=Failed to connect std%s of %s to the journal socket: %s",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering fileno == STDOUT_FILENO ? "out" : "err",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering unit_id, strerror(-r),
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering "ERRNO=%d", -r,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering NULL);
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering r = open_null_as(O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering case EXEC_OUTPUT_SOCKET:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(socket_fd >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
a3e7f417d72ba3251fd6b3a228a2721a4b725a03Zbigniew Jędrzejewski-Szmek
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering default:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert_not_reached("Unknown error type");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering}
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poetteringstatic int chown_terminal(int fd, uid_t uid) {
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering struct stat st;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering assert(fd >= 0);
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering /* This might fail. What matters are the results. */
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering (void) fchown(fd, uid, -1);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering (void) fchmod(fd, TTY_MODE);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (fstat(fd, &st) < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -errno;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return -EPERM;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering return 0;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering}
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poetteringstatic int setup_confirm_stdio(int *_saved_stdin,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int *_saved_stdout) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering int fd = -1, saved_stdin, saved_stdout = -1, r;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(_saved_stdin);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(_saved_stdout);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (saved_stdin < 0)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -errno;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (saved_stdout < 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = errno;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering goto fail;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering fd = acquire_terminal(
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering "/dev/console",
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering false,
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering false,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering false,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering DEFAULT_CONFIRM_USEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = fd;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering }
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = chown_terminal(fd, getuid());
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (r < 0)
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering goto fail;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (dup2(fd, STDIN_FILENO) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (dup2(fd, STDOUT_FILENO) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (fd >= 2)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering close_nointr_nofail(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *_saved_stdin = saved_stdin;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering *_saved_stdout = saved_stdout;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringfail:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (saved_stdout >= 0)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering close_nointr_nofail(saved_stdout);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (saved_stdin >= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(saved_stdin);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd >= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering close_nointr_nofail(fd);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int fd;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering va_list ap;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering assert(format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (fd < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return fd;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering va_start(ap, format);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering vdprintf(fd, format, ap);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering va_end(ap);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering close_nointr_nofail(fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poetteringstatic int restore_confirm_stdio(int *saved_stdin,
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering int *saved_stdout) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int r = 0;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(saved_stdin);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(saved_stdout);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering release_terminal();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (*saved_stdin >= 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (dup2(*saved_stdin, STDIN_FILENO) < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = -errno;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (*saved_stdout >= 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = -errno;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (*saved_stdin >= 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering close_nointr_nofail(*saved_stdin);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (*saved_stdout >= 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering close_nointr_nofail(*saved_stdout);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poetteringstatic int ask_for_confirmation(char *response, char **argv) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int saved_stdout = -1, saved_stdin = -1, r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering char *line;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering line = exec_command_line(argv);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (!line)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -ENOMEM;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = ask(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering free(line);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering restore_confirm_stdio(&saved_stdin, &saved_stdout);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering bool keep_groups = false;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(context);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* Lookup and set GID and supplementary group list. Here too
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * we avoid NSS lookups for gid=0. */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (context->group || username) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (context->group) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering const char *g = context->group;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if ((r = get_group_creds(&g, &gid)) < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* First step, initialize groups from /etc/groups */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (username && gid != 0) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (initgroups(username, gid) < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return -errno;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering keep_groups = true;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Second step, set our gids */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (setresgid(gid, gid, gid) < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (context->supplementary_groups) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int ngroups_max, k;
9030ca462bd13cd6536299814e4a71d5c5e85be9Lennart Poettering gid_t *gids;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering char **i;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering /* Final step, initialize any manually set supplementary groups */
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (!(gids = new(gid_t, ngroups_max)))
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return -ENOMEM;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if (keep_groups) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering if ((k = getgroups(ngroups_max, gids)) < 0) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering free(gids);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return -errno;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering }
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering } else
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering k = 0;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering STRV_FOREACH(i, context->supplementary_groups) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering const char *g;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (k >= ngroups_max) {
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering free(gids);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering return -E2BIG;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering g = *i;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering r = get_group_creds(&g, gids+k);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering if (r < 0) {
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering free(gids);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering return r;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering k++;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering if (setgroups(k, gids) < 0) {
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering free(gids);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering return -errno;
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering free(gids);
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering }
5f8cc96a0301c1177b11dd2e89370ef0b2ef577bLennart Poettering
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering return 0;
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering}
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poetteringstatic int enforce_user(const ExecContext *context, uid_t uid) {
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering int r;
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering assert(context);
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering /* Sets (but doesn't lookup) the uid and make sure we keep the
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering * capabilities while doing so. */
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering if (context->capabilities) {
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering cap_t d;
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering static const cap_value_t bits[] = {
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering CAP_SETUID, /* Necessary so that we can run setresuid() below */
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering };
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering /* First step: If we need to keep capabilities but
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering * drop privileges we need to make sure we keep our
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering * caps, while we drop privileges. */
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering if (uid != 0) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (prctl(PR_GET_SECUREBITS) != sb)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (prctl(PR_SET_SECUREBITS, sb) < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering return -errno;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering /* Second step: set the capabilities. This will reduce
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering * the capabilities to the minimum we need. */
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (!(d = cap_dup(context->capabilities)))
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering return -errno;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0) {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = -errno;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering cap_free(d);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering return r;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering if (cap_set_proc(d) < 0) {
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering r = -errno;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering cap_free(d);
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering return r;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering }
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering cap_free(d);
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering }
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering /* Third step: actually set the uids */
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering if (setresuid(uid, uid, uid) < 0)
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering return -errno;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering /* At this point we should have all necessary capabilities but
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering are otherwise a normal user. However, the caps might got
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering corrupted due to the setresuid() so we need clean them up
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering later. This is done outside of this call. */
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering return 0;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering}
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering#ifdef HAVE_PAM
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poetteringstatic int null_conv(
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering int num_msg,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering const struct pam_message **msg,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering struct pam_response **resp,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering void *appdata_ptr) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering /* We don't support conversations */
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return PAM_CONV_ERR;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering}
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poetteringstatic int setup_pam(
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering const char *name,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering const char *user,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering uid_t uid,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering const char *tty,
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering char ***pam_env,
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering int fds[], unsigned n_fds) {
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering static const struct pam_conv conv = {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering .conv = null_conv,
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering .appdata_ptr = NULL
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering };
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_handle_t *handle = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering sigset_t ss, old_ss;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int pam_code = PAM_SUCCESS;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int err;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering char **e = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering bool close_session = false;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pid_t pam_pid = 0, parent_pid;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int flags = 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(name);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(user);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(pam_env);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* We set up PAM in the parent process, then fork. The child
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * will then stay around until killed via PR_GET_PDEATHSIG or
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * systemd via the cgroup logic. It will then remove the PAM
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * session again. The parent process will exec() the actual
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering * daemon. We do things this way to ensure that the main PID
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering * of the daemon is the one we initially fork()ed. */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (log_get_max_level() < LOG_PRI(LOG_DEBUG))
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering flags |= PAM_SILENT;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering pam_code = pam_start(name, user, &conv, &handle);
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering if (pam_code != PAM_SUCCESS) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering handle = NULL;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (tty) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_code = pam_set_item(handle, PAM_TTY, tty);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (pam_code != PAM_SUCCESS)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_code = pam_acct_mgmt(handle, flags);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (pam_code != PAM_SUCCESS)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_code = pam_open_session(handle, flags);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (pam_code != PAM_SUCCESS)
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering goto fail;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering close_session = true;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering e = pam_getenvlist(handle);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (!e) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_code = PAM_BUF_ERR;
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering /* Block SIGTERM, so that we know that it won't get lost in
1ddb263d21099ae42195c2bc382bdf72a7f24f82Lennart Poettering * the child */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (sigemptyset(&ss) < 0 ||
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering sigaddset(&ss, SIGTERM) < 0 ||
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering parent_pid = getpid();
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering pam_pid = fork();
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (pam_pid < 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering goto fail;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (pam_pid == 0) {
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering int sig;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering int r = EXIT_PAM;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* The child's job is to reset the PAM session on
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering * termination */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* This string must fit in 10 chars (i.e. the length
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * of "/sbin/init"), to look pretty in /bin/ps */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering rename_process("(sd-pam)");
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering /* Make sure we don't keep open the passed fds in this
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering child. We assume that otherwise only those fds are
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering open here that have been opened by PAM. */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering close_many(fds, n_fds);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* Drop privileges - we don't need any to pam_close_session
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * and this will make PR_SET_PDEATHSIG work in most cases.
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * If this fails, ignore the error - but expect sd-pam threads
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * to fail to exit normally */
403ed0e5c914f2a0a683403d8ba7eaf96e3ffcdfMichael Chapman if (setresuid(uid, uid, uid) < 0)
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering log_error("Error: Failed to setresuid() in sd-pam: %s", strerror(-r));
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* Wait until our parent died. This will only work if
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * the above setresuid() succeeds, otherwise the kernel
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * will not allow unprivileged parents kill their privileged
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * children this way. We rely on the control groups kill logic
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * to do the rest for us. */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto child_finish;
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering /* Check if our parent process might already have
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering * died? */
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering if (getppid() == parent_pid) {
4cee5eede280b7fd48c18a1942616c4ac896a554Lennart Poettering for (;;) {
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering if (sigwait(&ss, &sig) < 0) {
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering if (errno == EINTR)
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering continue;
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering
efe0286285a7432f738fafae840fa4eda51c2986Lennart Poettering goto child_finish;
efe0286285a7432f738fafae840fa4eda51c2986Lennart Poettering }
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering assert(sig == SIGTERM);
5bcd08db289cd02aad8a89b37b2a46244a7bd473Lennart Poettering break;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
26166c88e0b47b83972f32b5057ecbffe06bf904Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* If our parent died we'll end the session */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (getppid() != parent_pid) {
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering pam_code = pam_close_session(handle, flags);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (pam_code != PAM_SUCCESS)
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto child_finish;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering r = 0;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering child_finish:
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering pam_end(handle, pam_code | flags);
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering _exit(r);
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering }
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* If the child was forked off successfully it will do all the
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * cleanups, so forget about the handle here. */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering handle = NULL;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* Unblock SIGTERM again in the parent */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering goto fail;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering /* We close the log explicitly here, since the PAM modules
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering * might have opened it, but we don't want this fd around. */
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering closelog();
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering *pam_env = e;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering e = NULL;
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringfail:
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (pam_code != PAM_SUCCESS) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("PAM failed: %s", pam_strerror(handle, pam_code));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering err = -EPERM; /* PAM errors do not map to errno */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering } else {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering log_error("PAM failed: %m");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering err = -errno;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (handle) {
c077529ba6852192c464772ce907670850210dfeLennart Poettering if (close_session)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering pam_code = pam_close_session(handle, flags);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering pam_end(handle, pam_code | flags);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering strv_free(e);
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering closelog();
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (pam_pid > 1) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering kill(pam_pid, SIGTERM);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering kill(pam_pid, SIGCONT);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return err;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering}
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering#endif
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringstatic void rename_process_from_path(const char *path) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering char process_name[11];
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering const char *p;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering size_t l;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek /* This resulting string must fit in 10 chars (i.e. the length
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * of "/sbin/init") to look pretty in /bin/ps */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering p = basename(path);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (isempty(p)) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering rename_process("(...)");
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering l = strlen(p);
c077529ba6852192c464772ce907670850210dfeLennart Poettering if (l > 8) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* The end of the process name is usually more
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * interesting, since the first bit might just be
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * "systemd-" */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering p = p + l - 8;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering l = 8;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering process_name[0] = '(';
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering memcpy(process_name+1, p, l);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering process_name[1+l] = ')';
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering process_name[1+l+1] = 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering rename_process(process_name);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering}
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringstatic int apply_seccomp(uint32_t *syscall_filter) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering static const struct sock_filter header[] = {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering VALIDATE_ARCHITECTURE,
c077529ba6852192c464772ce907670850210dfeLennart Poettering EXAMINE_SYSCALL
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering };
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering static const struct sock_filter footer[] = {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering _KILL_PROCESS
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering };
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering int i;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering unsigned n;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering struct sock_filter *f;
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering struct sock_fprog prog = {};
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering assert(syscall_filter);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* First: count the syscalls to check for */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering for (i = 0, n = 0; i < syscall_max(); i++)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (syscall_filter[i >> 4] & (1 << (i & 31)))
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* Second: build the filter program from a header the syscall
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering * matches and the footer */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering f = alloca(sizeof(struct sock_filter) * (ELEMENTSOF(header) + 2*n + ELEMENTSOF(footer)));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering memcpy(f, header, sizeof(header));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering for (i = 0, n = 0; i < syscall_max(); i++)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (syscall_filter[i >> 4] & (1 << (i & 31))) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering struct sock_filter item[] = {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1),
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering };
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering assert_cc(ELEMENTSOF(item) == 2);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering f[ELEMENTSOF(header) + 2*n] = item[0];
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering f[ELEMENTSOF(header) + 2*n+1] = item[1];
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n++;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering memcpy(f + (ELEMENTSOF(header) + 2*n), footer, sizeof(footer));
c077529ba6852192c464772ce907670850210dfeLennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* Third: install the filter */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering prog.len = ELEMENTSOF(header) + ELEMENTSOF(footer) + 2*n;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering prog.filter = f;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog) < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -errno;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering}
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringstatic void do_idle_pipe_dance(int idle_pipe[4]) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering assert(idle_pipe);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (idle_pipe[1] >= 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering close_nointr_nofail(idle_pipe[1]);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (idle_pipe[2] >= 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering close_nointr_nofail(idle_pipe[2]);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (idle_pipe[0] >= 0) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering int r;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* Signal systemd that we are bored and want to continue. */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering write(idle_pipe[3], "x", 1);
c077529ba6852192c464772ce907670850210dfeLennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering /* Wait for systemd to react to the signal above. */
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering close_nointr_nofail(idle_pipe[0]);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering }
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering if (idle_pipe[3] >= 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering close_nointr_nofail(idle_pipe[3]);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering}
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringstatic int build_environment(
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering ExecContext *c,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering unsigned n_fds,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering usec_t watchdog_usec,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering const char *home,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering const char *username,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering const char *shell,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering char ***ret) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering _cleanup_strv_free_ char **our_env = NULL;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering unsigned n_env = 0;
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek char *x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering assert(c);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering assert(ret);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env = new0(char*, 10);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!our_env)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (n_fds > 0) {
c077529ba6852192c464772ce907670850210dfeLennart Poettering if (asprintf(&x, "LISTEN_PID=%lu", (unsigned long) getpid()) < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (watchdog_usec > 0) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (asprintf(&x, "WATCHDOG_PID=%lu", (unsigned long) getpid()) < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (asprintf(&x, "WATCHDOG_USEC=%llu", (unsigned long long) watchdog_usec) < 0)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c077529ba6852192c464772ce907670850210dfeLennart Poettering if (home) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering x = strappend("HOME=", home);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!x)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (username) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering x = strappend("LOGNAME=", username);
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering if (!x)
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering return -ENOMEM;
a79366e22a43ed81017e2d8c2426431d369f3cfaLennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering x = strappend("USER=", username);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!x)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (shell) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering x = strappend("SHELL=", shell);
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!x)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (is_terminal_input(c->std_input) ||
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering c->std_output == EXEC_OUTPUT_TTY ||
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering c->std_error == EXEC_OUTPUT_TTY ||
b3267152783d5784c45010615045d4e8ee459da2Zbigniew Jędrzejewski-Szmek c->tty_path) {
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering x = strdup(default_term_for_tty(tty_path(c)));
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering if (!x)
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return -ENOMEM;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = x;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering }
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env[n_env++] = NULL;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering assert(n_env <= 10);
c077529ba6852192c464772ce907670850210dfeLennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering *ret = our_env;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering our_env = NULL;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering return 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering}
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poetteringint exec_spawn(ExecCommand *command,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering char **argv,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering ExecContext *context,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering int fds[], unsigned n_fds,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering char **environment,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering bool apply_permissions,
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering bool apply_chroot,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering bool apply_tty_stdin,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering bool confirm_spawn,
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering CGroupControllerMask cgroup_supported,
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering const char *cgroup_path,
160e3793adf2da2bd9ae3fe6b8881bb937e6e71bLennart Poettering const char *unit_id,
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering usec_t watchdog_usec,
c2ce6a3d82b717c4c1e6245ad8c6ce1173f502d0Lennart Poettering int idle_pipe[4],
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering ExecRuntime *runtime,
adacb9575a09981fcf11279f2f661e3fc21e58ffLennart Poettering pid_t *ret) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_strv_free_ char **files_env = NULL;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering int socket_fd;
8d07a7c47159ebc2bcc775e2c1997cb44bd1ac95Lennart Poettering char *line;
9b5ed6feda08290edce3bf916fa7362733dd30eaLennart Poettering pid_t pid;
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering int r;
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering
3a6fb33c54bc64398e0af1c9d7c74a6b614a849dLennart Poettering assert(command);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(context);
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering assert(ret);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering assert(fds || n_fds <= 0);
49af9e1368571f4e423cde0fd45ee284451434d1Lennart Poettering
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering if (context->std_input == EXEC_INPUT_SOCKET ||
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering context->std_output == EXEC_OUTPUT_SOCKET ||
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering context->std_error == EXEC_OUTPUT_SOCKET) {
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering if (n_fds != 1)
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering return -EINVAL;
70244d1d25eb80b57e160ea004d0e6bf793d4cafLennart Poettering
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering socket_fd = fds[0];
d6ce17c7f02ed3facdb45f65f546e587c2f00950Lennart Poettering
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering fds = NULL;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering n_fds = 0;
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering } else
c01ff965b48bb9693dcd77cbc748b5d8676766b0Lennart Poettering socket_fd = -1;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = exec_context_load_environment(context, &files_env);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (r < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering log_struct_unit(LOG_ERR,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unit_id,
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering "MESSAGE=Failed to load environment files: %s", strerror(-r),
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "ERRNO=%d", -r,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering NULL);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return r;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!argv)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering argv = command->argv;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering line = exec_command_line(argv);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!line)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering return log_oom();
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
65d73cf042ba7de11d254f5c4714f467db64b7c3Lennart Poettering log_struct_unit(LOG_DEBUG,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering unit_id,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering "EXECUTABLE=%s", command->path,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering "MESSAGE=About to execute: %s", line,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering NULL);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering free(line);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering pid = fork();
491ac9f2c4aeda8c40edde35112404b737e38b60Lennart Poettering if (pid < 0)
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering return -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (pid == 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering const char *username = NULL, *home = NULL, *shell = NULL;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering unsigned n_dont_close = 0;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering int dont_close[n_fds + 3];
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering uid_t uid = (uid_t) -1;
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering gid_t gid = (gid_t) -1;
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering sigset_t ss;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering int i, err;
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering /* child */
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering rename_process_from_path(command->path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering /* We reset exactly these signals, since they are the
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * only ones we set to SIG_IGN in the main daemon. All
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * others we leave untouched because we set them to
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * SIG_DFL or a valid handler initially, both of which
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering * will be demoted to SIG_DFL. */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering default_signals(SIGNALS_CRASH_HANDLER,
49f3fffd94591bdf2bd6c2233a9300daeab79566Lennart Poettering SIGNALS_IGNORE, -1);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (context->ignore_sigpipe)
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering ignore_signals(SIGPIPE, -1);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering assert_se(sigemptyset(&ss) == 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering err = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_SIGNAL_MASK;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering }
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (idle_pipe)
e5f5b5b9c92d59ef3cb5169982cb6f436c9206faLennart Poettering do_idle_pipe_dance(idle_pipe);
e5f5b5b9c92d59ef3cb5169982cb6f436c9206faLennart Poettering
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering /* Close sockets very early to make sure we don't
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering * block init reexecution because it cannot bind its
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering * sockets */
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering log_forget_fds();
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (socket_fd >= 0)
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering dont_close[n_dont_close++] = socket_fd;
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering if (n_fds > 0) {
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering n_dont_close += n_fds;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (runtime) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (runtime->netns_storage_socket[0] >= 0)
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (runtime->netns_storage_socket[1] >= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering err = close_all_fds(dont_close, n_dont_close);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (err < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_FDS;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering if (!context->same_pgrp)
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering if (setsid() < 0) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering err = -errno;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = EXIT_SETSID;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering }
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering if (context->tcpwrap_name) {
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering if (socket_fd >= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = -EACCES;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = EXIT_TCPWRAP;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering for (i = 0; i < (int) n_fds; i++) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (!socket_tcpwrap(fds[i], context->tcpwrap_name)) {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering err = -EACCES;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering r = EXIT_TCPWRAP;
190700621f95160d364f8ec1d3e360246c41ce75Lennart Poettering goto fail_child;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
65d73cf042ba7de11d254f5c4714f467db64b7c3Lennart Poettering exec_context_tty_reset(context);
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering if (confirm_spawn) {
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering char response;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering err = ask_for_confirmation(&response, argv);
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering if (err == -ETIMEDOUT)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering write_confirm_message("Confirmation question timed out, assuming positive response.\n");
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering else if (err < 0)
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
554604b3073467af75dc94fac9e2343148603289Lennart Poettering else if (response == 's') {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering write_confirm_message("Skipping execution.\n");
554604b3073467af75dc94fac9e2343148603289Lennart Poettering err = -ECANCELED;
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = EXIT_CONFIRM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering } else if (response == 'n') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering write_confirm_message("Failing execution.\n");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = r = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If a socket is connected to STDIN/STDOUT/STDERR, we
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * must sure to drop O_NONBLOCK */
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering if (socket_fd >= 0)
554604b3073467af75dc94fac9e2343148603289Lennart Poettering fd_nonblock(socket_fd, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = setup_input(context, socket_fd, apply_tty_stdin);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_STDIN;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_STDOUT;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
151b9b9662a90455262ce575a8a8ae74bf4ff336Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering r = EXIT_STDERR;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (cgroup_path) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = cg_attach_everywhere(cgroup_supported, cgroup_path, 0);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_CGROUP;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->oom_score_adjust_set) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char t[16];
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering char_array_0(t);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_OOM_ADJUST;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
554604b3073467af75dc94fac9e2343148603289Lennart Poettering }
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering if (context->nice_set)
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
a931ad47a8623163a29d898224d8a8c1177ffdafLennart Poettering err = -errno;
b370fec2b964c9ced48379824e896f44ad02a59aAlban Crequy r = EXIT_NICE;
b370fec2b964c9ced48379824e896f44ad02a59aAlban Crequy goto fail_child;
b370fec2b964c9ced48379824e896f44ad02a59aAlban Crequy }
b370fec2b964c9ced48379824e896f44ad02a59aAlban Crequy
554604b3073467af75dc94fac9e2343148603289Lennart Poettering if (context->cpu_sched_set) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering struct sched_param param = {
554604b3073467af75dc94fac9e2343148603289Lennart Poettering .sched_priority = context->cpu_sched_priority,
554604b3073467af75dc94fac9e2343148603289Lennart Poettering };
554604b3073467af75dc94fac9e2343148603289Lennart Poettering
554604b3073467af75dc94fac9e2343148603289Lennart Poettering r = sched_setscheduler(0,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->cpu_sched_policy |
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering (context->cpu_sched_reset_on_fork ?
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering SCHED_RESET_ON_FORK : 0),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering &param);
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering if (r < 0) {
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering err = -errno;
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering r = EXIT_SETSCHEDULER;
86b8d289717bad2800342efca0a5023aa8374e9cLennart Poettering goto fail_child;
c49b30a23583ff39daaa26696bcab478d2fee0bbLennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->cpuset)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_CPUAFFINITY;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (context->ioprio_set)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_IOPRIO;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->timer_slack_nsec != (nsec_t) -1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_TIMERSLACK;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->utmp_id)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->user) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering username = context->user;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = get_user_creds(&username, &uid, &gid, &home, &shell);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_USER;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (is_terminal_input(context->std_input)) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = chown_terminal(STDIN_FILENO, uid);
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_STDIN;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering#ifdef HAVE_PAM
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (cgroup_path && context->user && context->pam_name) {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0644, uid, gid);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering if (err < 0) {
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering r = EXIT_CGROUP;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, 0755, uid, gid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_CGROUP;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (apply_permissions) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = enforce_groups(context, username, gid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_GROUP;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering umask(context->umask);
de58a50e24a0d55e3bbcc77f8f6170a7322acf52Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_PAM
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (apply_permissions && context->pam_name && username) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_PAM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
a658cafa98ab55ea948c29bc87eb3945d515fb41Lennart Poettering err = setup_netns(runtime->netns_storage_socket);
de58a50e24a0d55e3bbcc77f8f6170a7322acf52Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_NETWORK;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering }
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!strv_isempty(context->read_write_dirs) ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !strv_isempty(context->read_only_dirs) ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !strv_isempty(context->inaccessible_dirs) ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering context->mount_flags != 0 ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *tmp = NULL, *var = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* The runtime struct only contains the parent
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * of the private /tmp, which is
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * non-accessible to world users. Inside of it
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * there's a /tmp that is sticky, and that's
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the one we want to use here. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->private_tmp && runtime) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (runtime->tmp_dir)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering tmp = strappenda(runtime->tmp_dir, "/tmp");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (runtime->var_tmp_dir)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering var = strappenda(runtime->var_tmp_dir, "/tmp");
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = setup_namespace(
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->read_write_dirs,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering context->read_only_dirs,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering context->inaccessible_dirs,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering tmp,
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering var,
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering context->mount_flags);
6797c324a653f119a3d7133122648aaa4878ddd6Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (err < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = EXIT_NAMESPACE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (apply_chroot) {
9b420b3cfb8b93daf50e4cdbc92b05f2209ef893Lennart Poettering if (context->root_directory)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (chroot(context->root_directory) < 0) {
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek err = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_CHROOT;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering goto fail_child;
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_CHDIR;
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering } else {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering _cleanup_free_ char *d = NULL;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (asprintf(&d, "%s/%s",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->root_directory ? context->root_directory : "",
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering context->working_directory ? context->working_directory : "") < 0) {
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = -ENOMEM;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_MEMORY;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering if (chdir(d) < 0) {
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek err = -errno;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering r = EXIT_CHDIR;
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering goto fail_child;
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek }
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek }
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek /* We repeat the fd closing here, to make sure that
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering * nothing is leaked from the PAM modules */
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = close_all_fds(fds, n_fds);
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek if (err >= 0)
c335068380fe8c9d843cdb2cf8a00f822cfabed3Lennart Poettering err = shift_fds(fds, n_fds);
bd16acf35e13a19cd2ded0a0c2ef774a98f73808Zbigniew Jędrzejewski-Szmek if (err >= 0)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers err = flags_fds(fds, n_fds, context->non_blocking);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (err < 0) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = EXIT_FDS;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers goto fail_child;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (apply_permissions) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers for (i = 0; i < RLIMIT_NLIMITS; i++) {
4a0b58c4a30ecaa61202f845ed86f75b36370cd0Lennart Poettering if (!context->rlimit[i])
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering continue;
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (setrlimit_closest(i, context->rlimit[i]) < 0) {
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering err = -errno;
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering r = EXIT_LIMITS;
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering goto fail_child;
077c8c366b58222629ed953abf2faa74ebadb769Lennart Poettering }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (context->capability_bounding_set_drop) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (err < 0) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = EXIT_CAPABILITIES;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers goto fail_child;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (context->user) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers err = enforce_user(context, uid);
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (err < 0) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers r = EXIT_USER;
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers goto fail_child;
fbe550738d03b178bb004a1390e74115e904118aLennart Poettering }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers }
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers /* PR_GET_SECUREBITS is not privileged, while
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers * PR_SET_SECUREBITS is. So to suppress
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers * potential EPERMs we'll try not to call
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers * PR_SET_SECUREBITS unless necessary. */
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
ab49725fd8587ef2b90dd0a67b2c915bc772d089Kay Sievers err = -errno;
r = EXIT_SECUREBITS;
goto fail_child;
}
if (context->capabilities)
if (cap_set_proc(context->capabilities) < 0) {
err = -errno;
r = EXIT_CAPABILITIES;
goto fail_child;
}
if (context->no_new_privileges)
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
err = -errno;
r = EXIT_NO_NEW_PRIVILEGES;
goto fail_child;
}
if (context->syscall_filter) {
err = apply_seccomp(context->syscall_filter);
if (err < 0) {
r = EXIT_SECCOMP;
goto fail_child;
}
}
}
err = build_environment(context, n_fds, watchdog_usec, home, username, shell, &our_env);
if (r < 0) {
r = EXIT_MEMORY;
goto fail_child;
}
final_env = strv_env_merge(5,
environment,
our_env,
context->environment,
files_env,
pam_env,
NULL);
if (!final_env) {
err = -ENOMEM;
r = EXIT_MEMORY;
goto fail_child;
}
final_argv = replace_env_argv(argv, final_env);
if (!final_argv) {
err = -ENOMEM;
r = EXIT_MEMORY;
goto fail_child;
}
final_env = strv_env_clean(final_env);
if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
line = exec_command_line(final_argv);
if (line) {
log_open();
log_struct_unit(LOG_DEBUG,
unit_id,
"EXECUTABLE=%s", command->path,
"MESSAGE=Executing: %s", line,
NULL);
log_close();
free(line);
line = NULL;
}
}
execve(command->path, final_argv, final_env);
err = -errno;
r = EXIT_EXEC;
fail_child:
if (r != 0) {
log_open();
log_struct(LOG_ERR, MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
"EXECUTABLE=%s", command->path,
"MESSAGE=Failed at step %s spawning %s: %s",
exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
command->path, strerror(-err),
"ERRNO=%d", -err,
NULL);
log_close();
}
_exit(r);
}
log_struct_unit(LOG_DEBUG,
unit_id,
"MESSAGE=Forked %s as %lu",
command->path, (unsigned long) pid,
NULL);
/* We add the new process to the cgroup both in the child (so
* that we can be sure that no user code is ever executed
* outside of the cgroup) and in the parent (so that we can be
* sure that when we kill the cgroup the process will be
* killed too). */
if (cgroup_path)
cg_attach(SYSTEMD_CGROUP_CONTROLLER, cgroup_path, pid);
exec_status_start(&command->exec_status, pid);
*ret = pid;
return 0;
}
void exec_context_init(ExecContext *c) {
assert(c);
c->umask = 0022;
c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
c->cpu_sched_policy = SCHED_OTHER;
c->syslog_priority = LOG_DAEMON|LOG_INFO;
c->syslog_level_prefix = true;
c->ignore_sigpipe = true;
c->timer_slack_nsec = (nsec_t) -1;
}
void exec_context_done(ExecContext *c) {
unsigned l;
assert(c);
strv_free(c->environment);
c->environment = NULL;
strv_free(c->environment_files);
c->environment_files = NULL;
for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
free(c->rlimit[l]);
c->rlimit[l] = NULL;
}
free(c->working_directory);
c->working_directory = NULL;
free(c->root_directory);
c->root_directory = NULL;
free(c->tty_path);
c->tty_path = NULL;
free(c->tcpwrap_name);
c->tcpwrap_name = NULL;
free(c->syslog_identifier);
c->syslog_identifier = NULL;
free(c->user);
c->user = NULL;
free(c->group);
c->group = NULL;
strv_free(c->supplementary_groups);
c->supplementary_groups = NULL;
free(c->pam_name);
c->pam_name = NULL;
if (c->capabilities) {
cap_free(c->capabilities);
c->capabilities = NULL;
}
strv_free(c->read_only_dirs);
c->read_only_dirs = NULL;
strv_free(c->read_write_dirs);
c->read_write_dirs = NULL;
strv_free(c->inaccessible_dirs);
c->inaccessible_dirs = NULL;
if (c->cpuset)
CPU_FREE(c->cpuset);
free(c->utmp_id);
c->utmp_id = NULL;
free(c->syscall_filter);
c->syscall_filter = NULL;
}
void exec_command_done(ExecCommand *c) {
assert(c);
free(c->path);
c->path = NULL;
strv_free(c->argv);
c->argv = NULL;
}
void exec_command_done_array(ExecCommand *c, unsigned n) {
unsigned i;
for (i = 0; i < n; i++)
exec_command_done(c+i);
}
void exec_command_free_list(ExecCommand *c) {
ExecCommand *i;
while ((i = c)) {
LIST_REMOVE(command, c, i);
exec_command_done(i);
free(i);
}
}
void exec_command_free_array(ExecCommand **c, unsigned n) {
unsigned i;
for (i = 0; i < n; i++) {
exec_command_free_list(c[i]);
c[i] = NULL;
}
}
int exec_context_load_environment(const ExecContext *c, char ***l) {
char **i, **r = NULL;
assert(c);
assert(l);
STRV_FOREACH(i, c->environment_files) {
char *fn;
int k;
bool ignore = false;
char **p;
_cleanup_globfree_ glob_t pglob = {};
int count, n;
fn = *i;
if (fn[0] == '-') {
ignore = true;
fn ++;
}
if (!path_is_absolute(fn)) {
if (ignore)
continue;
strv_free(r);
return -EINVAL;
}
/* Filename supports globbing, take all matching files */
errno = 0;
if (glob(fn, 0, NULL, &pglob) != 0) {
if (ignore)
continue;
strv_free(r);
return errno ? -errno : -EINVAL;
}
count = pglob.gl_pathc;
if (count == 0) {
if (ignore)
continue;
strv_free(r);
return -EINVAL;
}
for (n = 0; n < count; n++) {
k = load_env_file(pglob.gl_pathv[n], NULL, &p);
if (k < 0) {
if (ignore)
continue;
strv_free(r);
return k;
}
/* Log invalid environment variables with filename */
if (p)
p = strv_env_clean_log(p, pglob.gl_pathv[n]);
if (r == NULL)
r = p;
else {
char **m;
m = strv_env_merge(2, r, p);
strv_free(r);
strv_free(p);
if (!m)
return -ENOMEM;
r = m;
}
}
}
*l = r;
return 0;
}
static bool tty_may_match_dev_console(const char *tty) {
char *active = NULL, *console;
bool b;
if (startswith(tty, "/dev/"))
tty += 5;
/* trivial identity? */
if (streq(tty, "console"))
return true;
console = resolve_dev_console(&active);
/* if we could not resolve, assume it may */
if (!console)
return true;
/* "tty0" means the active VC, so it may be the same sometimes */
b = streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
free(active);
return b;
}
bool exec_context_may_touch_console(ExecContext *ec) {
return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
is_terminal_input(ec->std_input) ||
is_terminal_output(ec->std_output) ||
is_terminal_output(ec->std_error)) &&
tty_may_match_dev_console(tty_path(ec));
}
static void strv_fprintf(FILE *f, char **l) {
char **g;
assert(f);
STRV_FOREACH(g, l)
fprintf(f, " %s", *g);
}
void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
char **e;
unsigned i;
assert(c);
assert(f);
prefix = strempty(prefix);
fprintf(f,
"%sUMask: %04o\n"
"%sWorkingDirectory: %s\n"
"%sRootDirectory: %s\n"
"%sNonBlocking: %s\n"
"%sPrivateTmp: %s\n"
"%sPrivateNetwork: %s\n"
"%sIgnoreSIGPIPE: %s\n",
prefix, c->umask,
prefix, c->working_directory ? c->working_directory : "/",
prefix, c->root_directory ? c->root_directory : "/",
prefix, yes_no(c->non_blocking),
prefix, yes_no(c->private_tmp),
prefix, yes_no(c->private_network),
prefix, yes_no(c->ignore_sigpipe));
STRV_FOREACH(e, c->environment)
fprintf(f, "%sEnvironment: %s\n", prefix, *e);
STRV_FOREACH(e, c->environment_files)
fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
if (c->tcpwrap_name)
fprintf(f,
"%sTCPWrapName: %s\n",
prefix, c->tcpwrap_name);
if (c->nice_set)
fprintf(f,
"%sNice: %i\n",
prefix, c->nice);
if (c->oom_score_adjust_set)
fprintf(f,
"%sOOMScoreAdjust: %i\n",
prefix, c->oom_score_adjust);
for (i = 0; i < RLIM_NLIMITS; i++)
if (c->rlimit[i])
fprintf(f, "%s%s: %llu\n", prefix, rlimit_to_string(i), (unsigned long long) c->rlimit[i]->rlim_max);
if (c->ioprio_set) {
char *class_str;
int r;
r = ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
if (r < 0)
class_str = NULL;
fprintf(f,
"%sIOSchedulingClass: %s\n"
"%sIOPriority: %i\n",
prefix, strna(class_str),
prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
free(class_str);
}
if (c->cpu_sched_set) {
char *policy_str;
int r;
r = sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
if (r < 0)
policy_str = NULL;
fprintf(f,
"%sCPUSchedulingPolicy: %s\n"
"%sCPUSchedulingPriority: %i\n"
"%sCPUSchedulingResetOnFork: %s\n",
prefix, strna(policy_str),
prefix, c->cpu_sched_priority,
prefix, yes_no(c->cpu_sched_reset_on_fork));
free(policy_str);
}
if (c->cpuset) {
fprintf(f, "%sCPUAffinity:", prefix);
for (i = 0; i < c->cpuset_ncpus; i++)
if (CPU_ISSET_S(i, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset))
fprintf(f, " %u", i);
fputs("\n", f);
}
if (c->timer_slack_nsec != (nsec_t) -1)
fprintf(f, "%sTimerSlackNSec: %lu\n", prefix, (unsigned long)c->timer_slack_nsec);
fprintf(f,
"%sStandardInput: %s\n"
"%sStandardOutput: %s\n"
"%sStandardError: %s\n",
prefix, exec_input_to_string(c->std_input),
prefix, exec_output_to_string(c->std_output),
prefix, exec_output_to_string(c->std_error));
if (c->tty_path)
fprintf(f,
"%sTTYPath: %s\n"
"%sTTYReset: %s\n"
"%sTTYVHangup: %s\n"
"%sTTYVTDisallocate: %s\n",
prefix, c->tty_path,
prefix, yes_no(c->tty_reset),
prefix, yes_no(c->tty_vhangup),
prefix, yes_no(c->tty_vt_disallocate));
if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG || c->std_output == EXEC_OUTPUT_JOURNAL ||
c->std_output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_output == EXEC_OUTPUT_JOURNAL_AND_CONSOLE ||
c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG || c->std_error == EXEC_OUTPUT_JOURNAL ||
c->std_error == EXEC_OUTPUT_SYSLOG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_KMSG_AND_CONSOLE || c->std_error == EXEC_OUTPUT_JOURNAL_AND_CONSOLE) {
char *fac_str, *lvl_str;
int r;
r = log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
if (r < 0)
fac_str = NULL;
r = log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
if (r < 0)
lvl_str = NULL;
fprintf(f,
"%sSyslogFacility: %s\n"
"%sSyslogLevel: %s\n",
prefix, strna(fac_str),
prefix, strna(lvl_str));
free(lvl_str);
free(fac_str);
}
if (c->capabilities) {
char *t;
if ((t = cap_to_text(c->capabilities, NULL))) {
fprintf(f, "%sCapabilities: %s\n",
prefix, t);
cap_free(t);
}
}
if (c->secure_bits)
fprintf(f, "%sSecure Bits:%s%s%s%s%s%s\n",
prefix,
(c->secure_bits & 1<<SECURE_KEEP_CAPS) ? " keep-caps" : "",
(c->secure_bits & 1<<SECURE_KEEP_CAPS_LOCKED) ? " keep-caps-locked" : "",
(c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP) ? " no-setuid-fixup" : "",
(c->secure_bits & 1<<SECURE_NO_SETUID_FIXUP_LOCKED) ? " no-setuid-fixup-locked" : "",
(c->secure_bits & 1<<SECURE_NOROOT) ? " noroot" : "",
(c->secure_bits & 1<<SECURE_NOROOT_LOCKED) ? "noroot-locked" : "");
if (c->capability_bounding_set_drop) {
unsigned long l;
fprintf(f, "%sCapabilityBoundingSet:", prefix);
for (l = 0; l <= cap_last_cap(); l++)
if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
char *t;
if ((t = cap_to_name(l))) {
fprintf(f, " %s", t);
cap_free(t);
}
}
fputs("\n", f);
}
if (c->user)
fprintf(f, "%sUser: %s\n", prefix, c->user);
if (c->group)
fprintf(f, "%sGroup: %s\n", prefix, c->group);
if (strv_length(c->supplementary_groups) > 0) {
fprintf(f, "%sSupplementaryGroups:", prefix);
strv_fprintf(f, c->supplementary_groups);
fputs("\n", f);
}
if (c->pam_name)
fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
if (strv_length(c->read_write_dirs) > 0) {
fprintf(f, "%sReadWriteDirs:", prefix);
strv_fprintf(f, c->read_write_dirs);
fputs("\n", f);
}
if (strv_length(c->read_only_dirs) > 0) {
fprintf(f, "%sReadOnlyDirs:", prefix);
strv_fprintf(f, c->read_only_dirs);
fputs("\n", f);
}
if (strv_length(c->inaccessible_dirs) > 0) {
fprintf(f, "%sInaccessibleDirs:", prefix);
strv_fprintf(f, c->inaccessible_dirs);
fputs("\n", f);
}
if (c->utmp_id)
fprintf(f,
"%sUtmpIdentifier: %s\n",
prefix, c->utmp_id);
}
void exec_status_start(ExecStatus *s, pid_t pid) {
assert(s);
zero(*s);
s->pid = pid;
dual_timestamp_get(&s->start_timestamp);
}
void exec_status_exit(ExecStatus *s, ExecContext *context, pid_t pid, int code, int status) {
assert(s);
if (s->pid && s->pid != pid)
zero(*s);
s->pid = pid;
dual_timestamp_get(&s->exit_timestamp);
s->code = code;
s->status = status;
if (context) {
if (context->utmp_id)
utmp_put_dead_process(context->utmp_id, pid, code, status);
exec_context_tty_reset(context);
}
}
void exec_status_dump(ExecStatus *s, FILE *f, const char *prefix) {
char buf[FORMAT_TIMESTAMP_MAX];
assert(s);
assert(f);
if (!prefix)
prefix = "";
if (s->pid <= 0)
return;
fprintf(f,
"%sPID: %lu\n",
prefix, (unsigned long) s->pid);
if (s->start_timestamp.realtime > 0)
fprintf(f,
"%sStart Timestamp: %s\n",
prefix, format_timestamp(buf, sizeof(buf), s->start_timestamp.realtime));
if (s->exit_timestamp.realtime > 0)
fprintf(f,
"%sExit Timestamp: %s\n"
"%sExit Code: %s\n"
"%sExit Status: %i\n",
prefix, format_timestamp(buf, sizeof(buf), s->exit_timestamp.realtime),
prefix, sigchld_code_to_string(s->code),
prefix, s->status);
}
char *exec_command_line(char **argv) {
size_t k;
char *n, *p, **a;
bool first = true;
assert(argv);
k = 1;
STRV_FOREACH(a, argv)
k += strlen(*a)+3;
if (!(n = new(char, k)))
return NULL;
p = n;
STRV_FOREACH(a, argv) {
if (!first)
*(p++) = ' ';
else
first = false;
if (strpbrk(*a, WHITESPACE)) {
*(p++) = '\'';
p = stpcpy(p, *a);
*(p++) = '\'';
} else
p = stpcpy(p, *a);
}
*p = 0;
/* FIXME: this doesn't really handle arguments that have
* spaces and ticks in them */
return n;
}
void exec_command_dump(ExecCommand *c, FILE *f, const char *prefix) {
char *p2;
const char *prefix2;
char *cmd;
assert(c);
assert(f);
if (!prefix)
prefix = "";
p2 = strappend(prefix, "\t");
prefix2 = p2 ? p2 : prefix;
cmd = exec_command_line(c->argv);
fprintf(f,
"%sCommand Line: %s\n",
prefix, cmd ? cmd : strerror(ENOMEM));
free(cmd);
exec_status_dump(&c->exec_status, f, prefix2);
free(p2);
}
void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
assert(f);
if (!prefix)
prefix = "";
LIST_FOREACH(command, c, c)
exec_command_dump(c, f, prefix);
}
void exec_command_append_list(ExecCommand **l, ExecCommand *e) {
ExecCommand *end;
assert(l);
assert(e);
if (*l) {
/* It's kind of important, that we keep the order here */
LIST_FIND_TAIL(command, *l, end);
LIST_INSERT_AFTER(command, *l, end, e);
} else
*l = e;
}
int exec_command_set(ExecCommand *c, const char *path, ...) {
va_list ap;
char **l, *p;
assert(c);
assert(path);
va_start(ap, path);
l = strv_new_ap(path, ap);
va_end(ap);
if (!l)
return -ENOMEM;
p = strdup(path);
if (!p) {
strv_free(l);
return -ENOMEM;
}
free(c->path);
c->path = p;
strv_free(c->argv);
c->argv = l;
return 0;
}
static int exec_runtime_allocate(ExecRuntime **rt) {
if (*rt)
return 0;
*rt = new0(ExecRuntime, 1);
if (!*rt)
return -ENOMEM;
(*rt)->n_ref = 1;
(*rt)->netns_storage_socket[0] = (*rt)->netns_storage_socket[1] = -1;
return 0;
}
int exec_runtime_make(ExecRuntime **rt, ExecContext *c, const char *id) {
int r;
assert(rt);
assert(c);
assert(id);
if (*rt)
return 1;
if (!c->private_network && !c->private_tmp)
return 0;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
if (c->private_network && (*rt)->netns_storage_socket[0] < 0) {
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, (*rt)->netns_storage_socket) < 0)
return -errno;
}
if (c->private_tmp && !(*rt)->tmp_dir) {
r = setup_tmp_dirs(id, &(*rt)->tmp_dir, &(*rt)->var_tmp_dir);
if (r < 0)
return r;
}
return 1;
}
ExecRuntime *exec_runtime_ref(ExecRuntime *r) {
assert(r);
assert(r->n_ref > 0);
r->n_ref++;
return r;
}
ExecRuntime *exec_runtime_unref(ExecRuntime *r) {
if (!r)
return NULL;
assert(r->n_ref > 0);
r->n_ref--;
if (r->n_ref <= 0) {
free(r->tmp_dir);
free(r->var_tmp_dir);
close_pipe(r->netns_storage_socket);
free(r);
}
return NULL;
}
int exec_runtime_serialize(ExecRuntime *rt, Unit *u, FILE *f, FDSet *fds) {
assert(u);
assert(f);
assert(fds);
if (!rt)
return 0;
if (rt->tmp_dir)
unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir);
if (rt->var_tmp_dir)
unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir);
if (rt->netns_storage_socket[0] >= 0) {
int copy;
copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
if (copy < 0)
return copy;
unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy);
}
if (rt->netns_storage_socket[1] >= 0) {
int copy;
copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
if (copy < 0)
return copy;
unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy);
}
return 0;
}
int exec_runtime_deserialize_item(ExecRuntime **rt, Unit *u, const char *key, const char *value, FDSet *fds) {
int r;
assert(rt);
assert(key);
assert(value);
if (streq(key, "tmp-dir")) {
char *copy;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
copy = strdup(value);
if (!copy)
return log_oom();
free((*rt)->tmp_dir);
(*rt)->tmp_dir = copy;
} else if (streq(key, "var-tmp-dir")) {
char *copy;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
copy = strdup(value);
if (!copy)
return log_oom();
free((*rt)->var_tmp_dir);
(*rt)->var_tmp_dir = copy;
} else if (streq(key, "netns-socket-0")) {
int fd;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
else {
if ((*rt)->netns_storage_socket[0] >= 0)
close_nointr_nofail((*rt)->netns_storage_socket[0]);
(*rt)->netns_storage_socket[0] = fdset_remove(fds, fd);
}
} else if (streq(key, "netns-socket-1")) {
int fd;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_debug_unit(u->id, "Failed to parse netns socket value %s", value);
else {
if ((*rt)->netns_storage_socket[1] >= 0)
close_nointr_nofail((*rt)->netns_storage_socket[1]);
(*rt)->netns_storage_socket[1] = fdset_remove(fds, fd);
}
} else
return 0;
return 1;
}
static void *remove_tmpdir_thread(void *p) {
_cleanup_free_ char *path = p;
rm_rf_dangerous(path, false, true, false);
return NULL;
}
void exec_runtime_destroy(ExecRuntime *rt) {
if (!rt)
return;
/* If there are multiple users of this, let's leave the stuff around */
if (rt->n_ref > 1)
return;
if (rt->tmp_dir) {
log_debug("Spawning thread to nuke %s", rt->tmp_dir);
asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
rt->tmp_dir = NULL;
}
if (rt->var_tmp_dir) {
log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
rt->var_tmp_dir = NULL;
}
close_pipe(rt->netns_storage_socket);
}
static const char* const exec_input_table[_EXEC_INPUT_MAX] = {
[EXEC_INPUT_NULL] = "null",
[EXEC_INPUT_TTY] = "tty",
[EXEC_INPUT_TTY_FORCE] = "tty-force",
[EXEC_INPUT_TTY_FAIL] = "tty-fail",
[EXEC_INPUT_SOCKET] = "socket"
};
DEFINE_STRING_TABLE_LOOKUP(exec_input, ExecInput);
static const char* const exec_output_table[_EXEC_OUTPUT_MAX] = {
[EXEC_OUTPUT_INHERIT] = "inherit",
[EXEC_OUTPUT_NULL] = "null",
[EXEC_OUTPUT_TTY] = "tty",
[EXEC_OUTPUT_SYSLOG] = "syslog",
[EXEC_OUTPUT_SYSLOG_AND_CONSOLE] = "syslog+console",
[EXEC_OUTPUT_KMSG] = "kmsg",
[EXEC_OUTPUT_KMSG_AND_CONSOLE] = "kmsg+console",
[EXEC_OUTPUT_JOURNAL] = "journal",
[EXEC_OUTPUT_JOURNAL_AND_CONSOLE] = "journal+console",
[EXEC_OUTPUT_SOCKET] = "socket"
};
DEFINE_STRING_TABLE_LOOKUP(exec_output, ExecOutput);