execute.c revision 3cc2aff1abff9e34f9fec282d970204dc1eab6f1
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
8bdbb8d9cbe1d35708385573d70984ab4533812dLennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <signal.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/socket.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/un.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <sys/prctl.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <sys/stat.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <grp.h>
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering#include <poll.h>
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include <glob.h>
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering#include <utmpx.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/personality.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_PAM
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <security/pam_appl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#ifdef HAVE_SELINUX
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <selinux/selinux.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering#ifdef HAVE_SECCOMP
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <seccomp.h>
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#endif
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering#ifdef HAVE_APPARMOR
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include <sys/apparmor.h>
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#endif
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#include "sd-messages.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "rm-rf.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "capability.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "util.h"
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen#include "log.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "ioprio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "securebits.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "namespace.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "exit-status.h"
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include "missing.h"
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include "utmp-wtmp.h"
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#include "def.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "path-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "env-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "fileio.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "unit.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "async.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "selinux-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "errno-list.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "af-list.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "mkdir.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "smack-util.h"
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#include "bus-endpoint.h"
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#include "cap-list.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "formats-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "process-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "terminal-util.h"
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#include "signal-util.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_APPARMOR
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "apparmor-util.h"
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#endif
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SECCOMP
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "seccomp-util.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#endif
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include "execute.h"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen/* This assumes there is a 'tty' group */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define TTY_MODE 0620
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#define SNDBUF_SIZE (8*1024*1024)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int shift_fds(int fds[], unsigned n_fds) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int start, restart_from;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen if (n_fds <= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Modifies the fds array! (sorts it) */
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(fds);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering start = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (;;) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen restart_from = -1;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen for (i = start; i < (int) n_fds; i++) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int nfd;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering /* Already at right index? */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fds[i] == i+3)
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen continue;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering nfd = fcntl(fds[i], F_DUPFD, i + 3);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (nfd < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering safe_close(fds[i]);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fds[i] = nfd;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* Hmm, the fd we wanted isn't free? Then
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering * let's remember that and try again from here */
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (nfd != i+3 && restart_from < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering restart_from = i;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (restart_from < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering break;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering start = restart_from;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return 0;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poetteringstatic int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering unsigned i;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (n_fds <= 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return 0;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert(fds);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering for (i = 0; i < n_fds; i++) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = fd_nonblock(fds[i], nonblock);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* We unconditionally drop FD_CLOEXEC from the fds,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * since after all we want to pass these fds to our
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering * children */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = fd_cloexec(fds[i], false);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return 0;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering_pure_ static const char *tty_path(const ExecContext *context) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(context);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (context->tty_path)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return context->tty_path;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return "/dev/console";
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic void exec_context_tty_reset(const ExecContext *context) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(context);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (context->tty_vhangup)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering terminal_vhangup(tty_path(context));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (context->tty_reset)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering reset_terminal(tty_path(context));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (context->tty_vt_disallocate && context->tty_path)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering vt_disallocate(context->tty_path);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering}
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic bool is_terminal_output(ExecOutput o) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering o == EXEC_OUTPUT_TTY ||
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poetteringstatic int open_null_as(int flags, int nfd) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering int fd, r;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert(nfd >= 0);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering fd = open("/dev/null", flags|O_NOCTTY);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (fd < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (fd != nfd) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering safe_close(fd);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering } else
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = nfd;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int connect_journal_socket(int fd, uid_t uid, gid_t gid) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering union sockaddr_union sa = {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering .un.sun_family = AF_UNIX,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering .un.sun_path = "/run/systemd/journal/stdout",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering };
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering uid_t olduid = UID_INVALID;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering gid_t oldgid = GID_INVALID;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (gid != GID_INVALID) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering oldgid = getgid();
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering r = setegid(gid);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (r < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return -errno;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (uid != UID_INVALID) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering olduid = getuid();
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = seteuid(uid);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = -errno;
8937e7b68940d0fa0d0aab90eb7425fa7dccebc9Lennart Poettering goto restore_gid;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (r < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering /* If we fail to restore the uid or gid, things will likely
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fail later on. This should only happen if an LSM interferes. */
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (uid != UID_INVALID)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering (void) seteuid(olduid);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen restore_gid:
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (gid != GID_INVALID)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering (void) setegid(oldgid);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd, uid_t uid, gid_t gid) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering int fd, r;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(context);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(output < _EXEC_OUTPUT_MAX);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(ident);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(nfd >= 0);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM, 0);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (fd < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = connect_journal_socket(fd, uid, gid);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering if (r < 0)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (shutdown(fd, SHUT_RD) < 0) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering safe_close(fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering dprintf(fd,
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "%s\n"
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering "%s\n"
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering "%i\n"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "%i\n"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "%i\n"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "%i\n"
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering "%i\n",
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering context->syslog_identifier ? context->syslog_identifier : ident,
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering unit_id,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering context->syslog_priority,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering !!context->syslog_level_prefix,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering is_terminal_output(output));
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (fd != nfd) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering safe_close(fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering } else
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering r = nfd;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int open_terminal_as(const char *path, mode_t mode, int nfd) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int fd, r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(path);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(nfd >= 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fd = open_terminal(path, mode | O_NOCTTY);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (fd < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return fd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (fd != nfd) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering safe_close(fd);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = nfd;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic bool is_terminal_input(ExecInput i) {
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering return
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering i == EXEC_INPUT_TTY ||
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering i == EXEC_INPUT_TTY_FORCE ||
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering i == EXEC_INPUT_TTY_FAIL;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering}
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (is_terminal_input(std_input) && !apply_tty_stdin)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return EXEC_INPUT_NULL;
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return EXEC_INPUT_NULL;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return std_input;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int fixup_output(ExecOutput std_output, int socket_fd) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return EXEC_OUTPUT_INHERIT;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return std_output;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering ExecInput i;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(context);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering switch (i) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_INPUT_NULL:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return open_null_as(O_RDONLY, STDIN_FILENO);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_INPUT_TTY:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_INPUT_TTY_FORCE:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_INPUT_TTY_FAIL: {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int fd, r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering fd = acquire_terminal(tty_path(context),
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering i == EXEC_INPUT_TTY_FAIL,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering i == EXEC_INPUT_TTY_FORCE,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering false,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering USEC_INFINITY);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (fd < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return fd;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (fd != STDIN_FILENO) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering safe_close(fd);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering } else
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = STDIN_FILENO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering case EXEC_INPUT_SOCKET:
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering default:
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert_not_reached("Unknown input type");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int setup_output(Unit *unit, const ExecContext *context, int fileno, int socket_fd, const char *ident, bool apply_tty_stdin, uid_t uid, gid_t gid) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering ExecOutput o;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering ExecInput i;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(unit);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(context);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(ident);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering o = fixup_output(context->std_output, socket_fd);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (fileno == STDERR_FILENO) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering ExecOutput e;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering e = fixup_output(context->std_error, socket_fd);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* This expects the input and output are already set up */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Don't change the stderr file descriptor if we inherit all
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers * the way and are not on a tty */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (e == EXEC_OUTPUT_INHERIT &&
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering o == EXEC_OUTPUT_INHERIT &&
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers i == EXEC_INPUT_NULL &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !is_terminal_input(context->std_input) &&
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering getppid () != 1)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return fileno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Duplicate from stdout if possible */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (e == o || e == EXEC_OUTPUT_INHERIT)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o = e;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering } else if (o == EXEC_OUTPUT_INHERIT) {
56159e0d918e9a9be07988133bb2847779325de0Lennart 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... */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (i != EXEC_INPUT_NULL)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (getppid() != 1)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fileno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* We need to open /dev/null here anew, to get the right access mode. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return open_null_as(O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering switch (o) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_NULL:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return open_null_as(O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_TTY:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (is_terminal_input(i))
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* We don't reset the terminal if this is just about output */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_SYSLOG:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_KMSG:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_KMSG_AND_CONSOLE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_JOURNAL:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = connect_logger_as(context, o, ident, unit->id, fileno, uid, gid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering log_unit_error_errno(unit, r, "Failed to connect %s to the journal socket, ignoring: %m", fileno == STDOUT_FILENO ? "stdout" : "stderr");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = open_null_as(O_WRONLY, fileno);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering case EXEC_OUTPUT_SOCKET:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(socket_fd >= 0);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering default:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert_not_reached("Unknown error type");
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int chown_terminal(int fd, uid_t uid) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering struct stat st;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(fd >= 0);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* This might fail. What matters are the results. */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering (void) fchown(fd, uid, -1);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering (void) fchmod(fd, TTY_MODE);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (fstat(fd, &st) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return -EPERM;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poetteringstatic int setup_confirm_stdio(int *_saved_stdin,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering int *_saved_stdout) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int fd = -1, saved_stdin, saved_stdout = -1, r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(_saved_stdin);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering assert(_saved_stdout);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (saved_stdin < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (saved_stdout < 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering goto fail;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering fd = acquire_terminal(
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering "/dev/console",
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering false,
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek false,
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek false,
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering DEFAULT_CONFIRM_USEC);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (fd < 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = fd;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering goto fail;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = chown_terminal(fd, getuid());
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering if (dup2(fd, STDIN_FILENO) < 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering goto fail;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (dup2(fd, STDOUT_FILENO) < 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering goto fail;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (fd >= 2)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers safe_close(fd);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a6c616024db23fef34152c1432892824a07799ccLennart Poettering *_saved_stdin = saved_stdin;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering *_saved_stdout = saved_stdout;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poetteringfail:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(saved_stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(saved_stdin);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(fd);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt _cleanup_close_ int fd = -1;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt va_list ap;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd < 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers va_start(ap, format);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers vdprintf(fd, format, ap);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers va_end(ap);
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic int restore_confirm_stdio(int *saved_stdin,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers int *saved_stdout) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int r = 0;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(saved_stdin);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert(saved_stdout);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering release_terminal();
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (*saved_stdin >= 0)
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (dup2(*saved_stdin, STDIN_FILENO) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (*saved_stdout >= 0)
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = -errno;
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(*saved_stdin);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering safe_close(*saved_stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering}
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int ask_for_confirmation(char *response, char **argv) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering int saved_stdout = -1, saved_stdin = -1, r;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers _cleanup_free_ char *line = NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering line = exec_command_line(argv);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!line)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = ask_char(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers restore_confirm_stdio(&saved_stdin, &saved_stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return r;
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni}
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering bool keep_groups = false;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(context);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Lookup and set GID and supplementary group list. Here too
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * we avoid NSS lookups for gid=0. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (context->group || username) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (context->group) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *g = context->group;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen r = get_group_creds(&g, &gid);
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (r < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return r;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* First step, initialize groups from /etc/groups */
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering if (username && gid != 0) {
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering if (initgroups(username, gid) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering keep_groups = true;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Second step, set our gids */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (setresgid(gid, gid, gid) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (context->supplementary_groups) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int ngroups_max, k;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering gid_t *gids;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char **i;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Final step, initialize any manually set supplementary groups */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (!(gids = new(gid_t, ngroups_max)))
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return -ENOMEM;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (keep_groups) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k = getgroups(ngroups_max, gids);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (k < 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering free(gids);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -errno;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering } else
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k = 0;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering STRV_FOREACH(i, context->supplementary_groups) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *g;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (k >= ngroups_max) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering free(gids);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -E2BIG;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
9a14fb6285bdb089d4fc195410de3362cb4f586fThomas Hindoe Paaboel Andersen
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering g = *i;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = get_group_creds(&g, gids+k);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (r < 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering free(gids);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return r;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering k++;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (setgroups(k, gids) < 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering free(gids);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering free(gids);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return 0;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int enforce_user(const ExecContext *context, uid_t uid) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert(context);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* Sets (but doesn't lookup) the uid and make sure we keep the
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * capabilities while doing so. */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (context->capabilities) {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering _cleanup_cap_free_ cap_t d = NULL;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering static const cap_value_t bits[] = {
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering CAP_SETUID, /* Necessary so that we can run setresuid() below */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering };
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* First step: If we need to keep capabilities but
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * drop privileges we need to make sure we keep our
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * caps, while we drop privileges. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (uid != 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (prctl(PR_GET_SECUREBITS) != sb)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (prctl(PR_SET_SECUREBITS, sb) < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return -errno;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* Second step: set the capabilities. This will reduce
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * the capabilities to the minimum we need. */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering d = cap_dup(context->capabilities);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (!d)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return -errno;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (cap_set_proc(d) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Third step: actually set the uids */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (setresuid(uid, uid, uid) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* At this point we should have all necessary capabilities but
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering are otherwise a normal user. However, the caps might got
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering corrupted due to the setresuid() so we need clean them up
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering later. This is done outside of this call. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return 0;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering}
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering#ifdef HAVE_PAM
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int null_conv(
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int num_msg,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const struct pam_message **msg,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering struct pam_response **resp,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering void *appdata_ptr) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* We don't support conversations */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return PAM_CONV_ERR;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering}
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic int setup_pam(
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *name,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *user,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering uid_t uid,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *tty,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char ***pam_env,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int fds[], unsigned n_fds) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering static const struct pam_conv conv = {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering .conv = null_conv,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering .appdata_ptr = NULL
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering };
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_handle_t *handle = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering sigset_t old_ss;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int pam_code = PAM_SUCCESS;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int err;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char **e = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering bool close_session = false;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pid_t pam_pid = 0, parent_pid;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int flags = 0;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert(name);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert(user);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert(pam_env);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* We set up PAM in the parent process, then fork. The child
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * will then stay around until killed via PR_GET_PDEATHSIG or
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * systemd via the cgroup logic. It will then remove the PAM
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * session again. The parent process will exec() the actual
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * daemon. We do things this way to ensure that the main PID
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * of the daemon is the one we initially fork()ed. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (log_get_max_level() < LOG_DEBUG)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering flags |= PAM_SILENT;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_start(name, user, &conv, &handle);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering handle = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (tty) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_set_item(handle, PAM_TTY, tty);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_acct_mgmt(handle, flags);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_open_session(handle, flags);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering close_session = true;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering e = pam_getenvlist(handle);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (!e) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = PAM_BUF_ERR;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Block SIGTERM, so that we know that it won't get lost in
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * the child */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigprocmask_many(SIG_BLOCK, &old_ss, SIGTERM, -1) >= 0);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering parent_pid = getpid();
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering pam_pid = fork();
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (pam_pid < 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering goto fail;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (pam_pid == 0) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering int sig;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r = EXIT_PAM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* The child's job is to reset the PAM session on
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * termination */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* This string must fit in 10 chars (i.e. the length
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * of "/sbin/init"), to look pretty in /bin/ps */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen rename_process("(sd-pam)");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* Make sure we don't keep open the passed fds in this
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering child. We assume that otherwise only those fds are
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering open here that have been opened by PAM. */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering close_many(fds, n_fds);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* Drop privileges - we don't need any to pam_close_session
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * and this will make PR_SET_PDEATHSIG work in most cases.
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * If this fails, ignore the error - but expect sd-pam threads
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * to fail to exit normally */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (setresuid(uid, uid, uid) < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m");
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering (void) ignore_signals(SIGPIPE, -1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Wait until our parent died. This will only work if
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * the above setresuid() succeeds, otherwise the kernel
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * will not allow unprivileged parents kill their privileged
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering * children this way. We rely on the control groups kill logic
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering * to do the rest for us. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering goto child_finish;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Check if our parent process might already have
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * died? */
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering if (getppid() == parent_pid) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering sigset_t ss;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert_se(sigemptyset(&ss) >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert_se(sigaddset(&ss, SIGTERM) >= 0);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering for (;;) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (sigwait(&ss, &sig) < 0) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (errno == EINTR)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering continue;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering goto child_finish;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering assert(sig == SIGTERM);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering break;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering /* If our parent died we'll end the session */
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (getppid() != parent_pid) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering pam_code = pam_close_session(handle, flags);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (pam_code != PAM_SUCCESS)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering goto child_finish;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = 0;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering child_finish:
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering pam_end(handle, pam_code | flags);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering _exit(r);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering /* If the child was forked off successfully it will do all the
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * cleanups, so forget about the handle here. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering handle = NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Unblock SIGTERM again in the parent */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert_se(sigprocmask(SIG_SETMASK, &old_ss, NULL) >= 0);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* We close the log explicitly here, since the PAM modules
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * might have opened it, but we don't want this fd around. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering closelog();
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering *pam_env = e;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering e = NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return 0;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringfail:
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (pam_code != PAM_SUCCESS) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error("PAM failed: %s", pam_strerror(handle, pam_code));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering err = -EPERM; /* PAM errors do not map to errno */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering } else {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering log_error_errno(errno, "PAM failed: %m");
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering err = -errno;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (handle) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (close_session)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering pam_code = pam_close_session(handle, flags);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering pam_end(handle, pam_code | flags);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering strv_free(e);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering closelog();
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (pam_pid > 1) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering kill(pam_pid, SIGTERM);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering kill(pam_pid, SIGCONT);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return err;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering}
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#endif
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic void rename_process_from_path(const char *path) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering char process_name[11];
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const char *p;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering size_t l;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* This resulting string must fit in 10 chars (i.e. the length
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering * of "/sbin/init") to look pretty in /bin/ps */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering p = basename(path);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (isempty(p)) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering rename_process("(...)");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering l = strlen(p);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (l > 8) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* The end of the process name is usually more
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * interesting, since the first bit might just be
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * "systemd-" */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering p = p + l - 8;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering l = 8;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering process_name[0] = '(';
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering memcpy(process_name+1, p, l);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering process_name[1+l] = ')';
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering process_name[1+l+1] = 0;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering rename_process(process_name);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering}
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering#ifdef HAVE_SECCOMP
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringstatic int apply_seccomp(const ExecContext *c) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering uint32_t negative_action, action;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering scmp_filter_ctx *seccomp;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering Iterator i;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering void *id;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering int r;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering assert(c);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (!seccomp)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return -ENOMEM;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (c->syscall_archs) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering SET_FOREACH(id, c->syscall_archs, i) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r == -EEXIST)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering continue;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r < 0)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering goto finish;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering } else {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_add_secondary_archs(seccomp);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r < 0)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering goto finish;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering SET_FOREACH(id, c->syscall_filter, i) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r < 0)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering goto finish;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r < 0)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering goto finish;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_load(seccomp);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringfinish:
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering seccomp_release(seccomp);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return r;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering}
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poetteringstatic int apply_address_families(const ExecContext *c) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering scmp_filter_ctx *seccomp;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering Iterator i;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering int r;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering assert(c);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering seccomp = seccomp_init(SCMP_ACT_ALLOW);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (!seccomp)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return -ENOMEM;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering r = seccomp_add_secondary_archs(seccomp);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (c->address_families_whitelist) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering int af, first = 0, last = 0;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering void *afp;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* If this is a whitelist, we first block the address
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * families that are out of range and then everything
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * that is not in the set. First, we find the lowest
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * and highest address family in the set. */
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering SET_FOREACH(afp, c->address_families, i) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering af = PTR_TO_INT(afp);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (af <= 0 || af >= af_max())
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering continue;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (first == 0 || af < first)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering first = af;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (last == 0 || af > last)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering last = af;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert((first == 0) == (last == 0));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (first == 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* No entries in the valid range, block everything */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_rule_add(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_SYS(socket),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering 0);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering } else {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Block everything below the first entry */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_rule_add(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_SYS(socket),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering 1,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_A0(SCMP_CMP_LT, first));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Block everything above the last entry */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_rule_add(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_SYS(socket),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering 1,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_A0(SCMP_CMP_GT, last));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Block everything between the first and last
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * entry */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering for (af = 1; af < af_max(); af++) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (set_contains(c->address_families, INT_TO_PTR(af)))
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering continue;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_rule_add(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_SYS(socket),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering 1,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_A0(SCMP_CMP_EQ, af));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering } else {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering void *af;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* If this is a blacklist, then generate one rule for
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * each address family that are then combined in OR
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * checks. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SET_FOREACH(af, c->address_families, i) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = seccomp_rule_add(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_SYS(socket),
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering 1,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = seccomp_load(seccomp);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringfinish:
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering seccomp_release(seccomp);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return r;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering}
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#endif
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic void do_idle_pipe_dance(int idle_pipe[4]) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert(idle_pipe);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering safe_close(idle_pipe[1]);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering safe_close(idle_pipe[2]);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (idle_pipe[0] >= 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering int r;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Signal systemd that we are bored and want to continue. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = write(idle_pipe[3], "x", 1);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r > 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Wait for systemd to react to the signal above. */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering safe_close(idle_pipe[0]);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering safe_close(idle_pipe[3]);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering}
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poetteringstatic int build_environment(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const ExecContext *c,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering unsigned n_fds,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering usec_t watchdog_usec,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const char *home,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const char *username,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const char *shell,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering char ***ret) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering _cleanup_strv_free_ char **our_env = NULL;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering unsigned n_env = 0;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering char *x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert(c);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert(ret);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env = new0(char*, 10);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (!our_env)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (n_fds > 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env[n_env++] = x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env[n_env++] = x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (watchdog_usec > 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env[n_env++] = x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, watchdog_usec) < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env[n_env++] = x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (home) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering x = strappend("HOME=", home);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (!x)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering our_env[n_env++] = x;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (username) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering x = strappend("LOGNAME=", username);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (!x)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return -ENOMEM;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env[n_env++] = x;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering x = strappend("USER=", username);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (!x)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return -ENOMEM;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env[n_env++] = x;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering }
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (shell) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering x = strappend("SHELL=", shell);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (!x)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return -ENOMEM;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env[n_env++] = x;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering }
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (is_terminal_input(c->std_input) ||
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering c->std_output == EXEC_OUTPUT_TTY ||
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering c->std_error == EXEC_OUTPUT_TTY ||
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering c->tty_path) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering x = strdup(default_term_for_tty(tty_path(c)));
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering if (!x)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return -ENOMEM;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering our_env[n_env++] = x;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering }
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering our_env[n_env++] = NULL;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering assert(n_env <= 10);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering *ret = our_env;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env = NULL;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
bf441e3d9371a7e5aa1def66cfc40f0118884644Lennart Poettering
de33fc625725d199629ed074d6278504deb23debLennart Poetteringstatic bool exec_needs_mount_namespace(
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering const ExecContext *context,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const ExecParameters *params,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ExecRuntime *runtime) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(context);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt assert(params);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering if (!strv_isempty(context->read_write_dirs) ||
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering !strv_isempty(context->read_only_dirs) ||
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt !strv_isempty(context->inaccessible_dirs))
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt return true;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (context->mount_flags != 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return true;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir))
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return true;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (params->bus_endpoint_path)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return true;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (context->private_devices ||
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering context->protect_system != PROTECT_SYSTEM_NO ||
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering context->protect_home != PROTECT_HOME_NO)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return true;
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering return false;
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering}
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poetteringstatic int exec_child(
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering Unit *unit,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering ExecCommand *command,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering const ExecContext *context,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering const ExecParameters *params,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering ExecRuntime *runtime,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering char **argv,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering int socket_fd,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering int *fds, unsigned n_fds,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering char **files_env,
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering int *exit_status) {
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering _cleanup_free_ char *mac_selinux_context_net = NULL;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering const char *username = NULL, *home = NULL, *shell = NULL;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering unsigned n_dont_close = 0;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering int dont_close[n_fds + 4];
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering uid_t uid = UID_INVALID;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering gid_t gid = GID_INVALID;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering int i, r;
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering bool needs_mount_namespace;
ee451d766a64117a41ec36dd71e61683c9d9b83cLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(unit);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(command);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(context);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(params);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(exit_status);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering rename_process_from_path(command->path);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering /* We reset exactly these signals, since they are the
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering * only ones we set to SIG_IGN in the main daemon. All
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering * others we leave untouched because we set them to
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt * SIG_DFL or a valid handler initially, both of which
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt * will be demoted to SIG_DFL. */
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering (void) default_signals(SIGNALS_CRASH_HANDLER,
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering SIGNALS_IGNORE, -1);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (context->ignore_sigpipe)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering (void) ignore_signals(SIGPIPE, -1);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = reset_signal_mask();
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering if (r < 0) {
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering *exit_status = EXIT_SIGNAL_MASK;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return r;
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering }
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (params->idle_pipe)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering do_idle_pipe_dance(params->idle_pipe);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering /* Close sockets very early to make sure we don't
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering * block init reexecution because it cannot bind its
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * sockets */
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering log_forget_fds();
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (socket_fd >= 0)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering dont_close[n_dont_close++] = socket_fd;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (n_fds > 0) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering n_dont_close += n_fds;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (params->bus_endpoint_fd >= 0)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering dont_close[n_dont_close++] = params->bus_endpoint_fd;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (runtime) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (runtime->netns_storage_socket[0] >= 0)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (runtime->netns_storage_socket[1] >= 0)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering r = close_all_fds(dont_close, n_dont_close);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (r < 0) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering *exit_status = EXIT_FDS;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return r;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (!context->same_pgrp)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (setsid() < 0) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering *exit_status = EXIT_SETSID;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -errno;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering exec_context_tty_reset(context);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (params->confirm_spawn) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering char response;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = ask_for_confirmation(&response, argv);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r == -ETIMEDOUT)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering write_confirm_message("Confirmation question timed out, assuming positive response.\n");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering else if (r < 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-r));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering else if (response == 's') {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering write_confirm_message("Skipping execution.\n");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_CONFIRM;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return -ECANCELED;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering } else if (response == 'n') {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering write_confirm_message("Failing execution.\n");
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (context->user) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering username = context->user;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = get_user_creds(&username, &uid, &gid, &home, &shell);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_USER;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* If a socket is connected to STDIN/STDOUT/STDERR, we
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * must sure to drop O_NONBLOCK */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (socket_fd >= 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering fd_nonblock(socket_fd, false);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = setup_input(context, socket_fd, params->apply_tty_stdin);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_STDIN;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = setup_output(unit, context, STDOUT_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_STDOUT;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = setup_output(unit, context, STDERR_FILENO, socket_fd, basename(command->path), params->apply_tty_stdin, uid, gid);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_STDERR;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (params->cgroup_path) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_CGROUP;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (context->oom_score_adjust_set) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering char t[DECIMAL_STR_MAX(context->oom_score_adjust)];
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* When we can't make this change due to EPERM, then
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * let's silently skip over it. User namespaces
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * prohibit write access to this file, and we
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * shouldn't trip up over that. */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering sprintf(t, "%i", context->oom_score_adjust);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering r = write_string_file("/proc/self/oom_score_adj", t, 0);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (r == -EPERM || r == -EACCES) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_open();
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_unit_debug_errno(unit, r, "Failed to adjust OOM setting, assuming containerized execution, ignoring: %m");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering log_close();
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering } else if (r < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_OOM_ADJUST;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->nice_set)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_NICE;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->cpu_sched_set) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering struct sched_param param = {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering .sched_priority = context->cpu_sched_priority,
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering };
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = sched_setscheduler(0,
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering context->cpu_sched_policy |
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering (context->cpu_sched_reset_on_fork ?
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering SCHED_RESET_ON_FORK : 0),
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering &param);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (r < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_SETSCHEDULER;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->cpuset)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_CPUAFFINITY;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->ioprio_set)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_IOPRIO;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->timer_slack_nsec != NSEC_INFINITY)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_TIMERSLACK;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->personality != PERSONALITY_INVALID)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (personality(context->personality) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_PERSONALITY;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->utmp_id)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path,
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering context->utmp_mode == EXEC_UTMP_INIT ? INIT_PROCESS :
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering context->utmp_mode == EXEC_UTMP_LOGIN ? LOGIN_PROCESS :
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering USER_PROCESS,
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering username ? "root" : context->user);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->user && is_terminal_input(context->std_input)) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering r = chown_terminal(STDIN_FILENO, uid);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_STDIN;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return r;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_BUS_ENDPOINT;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering /* If delegation is enabled we'll pass ownership of the cgroup
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * (but only in systemd's own controller hierarchy!) to the
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * user of the new process. */
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (params->cgroup_path && context->user && params->cgroup_delegate) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_CGROUP;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_CGROUP;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering char **rt;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering STRV_FOREACH(rt, context->runtime_directory) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering _cleanup_free_ char *p;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering p = strjoin(params->runtime_prefix, "/", *rt, NULL);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (!p) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_RUNTIME_DIRECTORY;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -ENOMEM;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = mkdir_p_label(p, context->runtime_directory_mode);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_RUNTIME_DIRECTORY;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = chmod_and_chown(p, context->runtime_directory_mode, uid, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_RUNTIME_DIRECTORY;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (params->apply_permissions) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = enforce_groups(context, username, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_GROUP;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering umask(context->umask);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#ifdef HAVE_PAM
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (params->apply_permissions && context->pam_name && username) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_PAM;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#endif
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = setup_netns(runtime->netns_storage_socket);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_NETWORK;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return r;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering needs_mount_namespace = exec_needs_mount_namespace(context, params, runtime);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (needs_mount_namespace) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering char *tmp = NULL, *var = NULL;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering /* The runtime struct only contains the parent
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * of the private /tmp, which is
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * non-accessible to world users. Inside of it
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * there's a /tmp that is sticky, and that's
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering * the one we want to use here. */
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->private_tmp && runtime) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (runtime->tmp_dir)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering tmp = strjoina(runtime->tmp_dir, "/tmp");
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (runtime->var_tmp_dir)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering var = strjoina(runtime->var_tmp_dir, "/tmp");
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering r = setup_namespace(
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering params->apply_chroot ? context->root_directory : NULL,
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering context->read_write_dirs,
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering context->read_only_dirs,
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering context->inaccessible_dirs,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering tmp,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering var,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering params->bus_endpoint_path,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering context->private_devices,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering context->protect_home,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering context->protect_system,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering context->mount_flags);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering /* If we couldn't set up the namespace this is
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering * probably due to a missing capability. In this case,
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering * silently proceeed. */
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (r == -EPERM || r == -EACCES) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering log_open();
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_unit_debug_errno(unit, r, "Failed to set up namespace, assuming containerized execution, ignoring: %m");
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering log_close();
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering } else if (r < 0) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering *exit_status = EXIT_NAMESPACE;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return r;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (params->apply_chroot) {
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (!needs_mount_namespace && context->root_directory)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (chroot(context->root_directory) < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *exit_status = EXIT_CHROOT;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (chdir(context->working_directory ?: "/") < 0 &&
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering !context->working_directory_missing_ok) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_CHDIR;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering return -errno;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering } else {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering _cleanup_free_ char *d = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (asprintf(&d, "%s/%s",
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering context->root_directory ?: "",
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering context->working_directory ?: "") < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *exit_status = EXIT_MEMORY;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return -ENOMEM;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (chdir(d) < 0 &&
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering !context->working_directory_missing_ok) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_CHDIR;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_SELINUX
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen r = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering *exit_status = EXIT_SELINUX_CONTEXT;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* We repeat the fd closing here, to make sure that
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * nothing is leaked from the PAM modules. Note that
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * we are more aggressive this time since socket_fd
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * and the netns fds we don't need anymore. The custom
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * endpoint fd was needed to upload the policy and can
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen * now be closed as well. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = close_all_fds(fds, n_fds);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r >= 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = shift_fds(fds, n_fds);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (r >= 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering r = flags_fds(fds, n_fds, context->non_blocking);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *exit_status = EXIT_FDS;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (params->apply_permissions) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < _RLIMIT_MAX; i++) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!context->rlimit[i])
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (setrlimit_closest(i, context->rlimit[i]) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_LIMITS;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->capability_bounding_set_drop) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_CAPABILITIES;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering#ifdef HAVE_SMACK
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->smack_process_label) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = mac_smack_apply_pid(0, context->smack_process_label);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_SMACK_PROCESS_LABEL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef SMACK_DEFAULT_PROCESS_LABEL
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *exec_label = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = mac_smack_read(command->path, SMACK_ATTR_EXEC, &exec_label);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0 && r != -ENODATA && r != -EOPNOTSUPP) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_SMACK_PROCESS_LABEL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = mac_smack_apply_pid(0, exec_label ? : SMACK_DEFAULT_PROCESS_LABEL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen *exit_status = EXIT_SMACK_PROCESS_LABEL;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen return r;
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen }
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->user) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = enforce_user(context, uid);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_USER;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* PR_GET_SECUREBITS is not privileged, while
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * PR_SET_SECUREBITS is. So to suppress
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering * potential EPERMs we'll try not to call
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering * PR_SET_SECUREBITS unless necessary. */
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering *exit_status = EXIT_SECUREBITS;
de33fc625725d199629ed074d6278504deb23debLennart Poettering return -errno;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->capabilities)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (cap_set_proc(context->capabilities) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering *exit_status = EXIT_CAPABILITIES;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -errno;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering }
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (context->no_new_privileges)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering *exit_status = EXIT_NO_NEW_PRIVILEGES;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#ifdef HAVE_SECCOMP
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->address_families_whitelist ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering !set_isempty(context->address_families)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = apply_address_families(context);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering *exit_status = EXIT_ADDRESS_FAMILIES;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->syscall_whitelist ||
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering !set_isempty(context->syscall_filter) ||
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering !set_isempty(context->syscall_archs)) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = apply_seccomp(context);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (r < 0) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering *exit_status = EXIT_SECCOMP;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return r;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering#endif
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#ifdef HAVE_SELINUX
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (mac_selinux_use()) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering char *exec_context = mac_selinux_context_net ?: context->selinux_context;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (exec_context) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = setexeccon(exec_context);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (r < 0) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering *exit_status = EXIT_SELINUX_CONTEXT;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return r;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering#endif
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#ifdef HAVE_APPARMOR
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (context->apparmor_profile && mac_apparmor_use()) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = aa_change_onexec(context->apparmor_profile);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0 && !context->apparmor_profile_ignore) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering *exit_status = EXIT_APPARMOR_PROFILE;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering#endif
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = build_environment(context, n_fds, params->watchdog_usec, home, username, shell, &our_env);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *exit_status = EXIT_MEMORY;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering final_env = strv_env_merge(5,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering params->environment,
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering our_env,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen context->environment,
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt files_env,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen pam_env,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen NULL);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!final_env) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering *exit_status = EXIT_MEMORY;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering final_argv = replace_env_argv(argv, final_env);
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering if (!final_argv) {
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering *exit_status = EXIT_MEMORY;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering return -ENOMEM;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
final_env = strv_env_clean(final_env);
if (_unlikely_(log_get_max_level() >= LOG_DEBUG)) {
_cleanup_free_ char *line;
line = exec_command_line(final_argv);
if (line) {
log_open();
log_struct(LOG_DEBUG,
LOG_UNIT_ID(unit),
"EXECUTABLE=%s", command->path,
LOG_UNIT_MESSAGE(unit, "Executing: %s", line),
NULL);
log_close();
}
}
execve(command->path, final_argv, final_env);
*exit_status = EXIT_EXEC;
return -errno;
}
int exec_spawn(Unit *unit,
ExecCommand *command,
const ExecContext *context,
const ExecParameters *params,
ExecRuntime *runtime,
pid_t *ret) {
_cleanup_strv_free_ char **files_env = NULL;
int *fds = NULL; unsigned n_fds = 0;
_cleanup_free_ char *line = NULL;
int socket_fd, r;
char **argv;
pid_t pid;
assert(unit);
assert(command);
assert(context);
assert(ret);
assert(params);
assert(params->fds || params->n_fds <= 0);
if (context->std_input == EXEC_INPUT_SOCKET ||
context->std_output == EXEC_OUTPUT_SOCKET ||
context->std_error == EXEC_OUTPUT_SOCKET) {
if (params->n_fds != 1) {
log_unit_error(unit, "Got more than one socket.");
return -EINVAL;
}
socket_fd = params->fds[0];
} else {
socket_fd = -1;
fds = params->fds;
n_fds = params->n_fds;
}
r = exec_context_load_environment(unit, context, &files_env);
if (r < 0)
return log_unit_error_errno(unit, r, "Failed to load environment files: %m");
argv = params->argv ?: command->argv;
line = exec_command_line(argv);
if (!line)
return log_oom();
log_struct(LOG_DEBUG,
LOG_UNIT_ID(unit),
LOG_UNIT_MESSAGE(unit, "About to execute: %s", line),
"EXECUTABLE=%s", command->path,
NULL);
pid = fork();
if (pid < 0)
return log_unit_error_errno(unit, r, "Failed to fork: %m");
if (pid == 0) {
int exit_status;
r = exec_child(unit,
command,
context,
params,
runtime,
argv,
socket_fd,
fds, n_fds,
files_env,
&exit_status);
if (r < 0) {
log_open();
log_struct_errno(LOG_ERR, r,
LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
LOG_UNIT_ID(unit),
LOG_UNIT_MESSAGE(unit, "Failed at step %s spawning %s: %m",
exit_status_to_string(exit_status, EXIT_STATUS_SYSTEMD),
command->path),
"EXECUTABLE=%s", command->path,
NULL);
}
_exit(exit_status);
}
log_unit_debug(unit, "Forked %s as "PID_FMT, command->path, pid);
/* 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 (params->cgroup_path)
(void) cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->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_INFINITY;
c->personality = PERSONALITY_INVALID;
c->runtime_directory_mode = 0755;
}
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++) {
c->rlimit[l] = mfree(c->rlimit[l]);
}
c->working_directory = mfree(c->working_directory);
c->root_directory = mfree(c->root_directory);
c->tty_path = mfree(c->tty_path);
c->syslog_identifier = mfree(c->syslog_identifier);
c->user = mfree(c->user);
c->group = mfree(c->group);
strv_free(c->supplementary_groups);
c->supplementary_groups = NULL;
c->pam_name = mfree(c->pam_name);
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);
c->utmp_id = mfree(c->utmp_id);
c->selinux_context = mfree(c->selinux_context);
c->apparmor_profile = mfree(c->apparmor_profile);
set_free(c->syscall_filter);
c->syscall_filter = NULL;
set_free(c->syscall_archs);
c->syscall_archs = NULL;
set_free(c->address_families);
c->address_families = NULL;
strv_free(c->runtime_directory);
c->runtime_directory = NULL;
bus_endpoint_free(c->bus_endpoint);
c->bus_endpoint = NULL;
}
int exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
char **i;
assert(c);
if (!runtime_prefix)
return 0;
STRV_FOREACH(i, c->runtime_directory) {
_cleanup_free_ char *p;
p = strjoin(runtime_prefix, "/", *i, NULL);
if (!p)
return -ENOMEM;
/* We execute this synchronously, since we need to be
* sure this is gone when we start the service
* next. */
(void) rm_rf(p, REMOVE_ROOT);
}
return 0;
}
void exec_command_done(ExecCommand *c) {
assert(c);
c->path = mfree(c->path);
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);
}
ExecCommand* exec_command_free_list(ExecCommand *c) {
ExecCommand *i;
while ((i = c)) {
LIST_REMOVE(command, c, i);
exec_command_done(i);
free(i);
}
return NULL;
}
void exec_command_free_array(ExecCommand **c, unsigned n) {
unsigned i;
for (i = 0; i < n; i++)
c[i] = exec_command_free_list(c[i]);
}
typedef struct InvalidEnvInfo {
Unit *unit;
const char *path;
} InvalidEnvInfo;
static void invalid_env(const char *p, void *userdata) {
InvalidEnvInfo *info = userdata;
log_unit_error(info->unit, "Ignoring invalid environment assignment '%s': %s", p, info->path);
}
int exec_context_load_environment(Unit *unit, 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(NULL, 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) {
InvalidEnvInfo info = {
.unit = unit,
.path = pglob.gl_pathv[n]
};
p = strv_env_clean_with_callback(p, invalid_env, &info);
}
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) {
_cleanup_free_ char *active = NULL;
char *console;
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 */
return streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
}
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"
"%sPrivateDevices: %s\n"
"%sProtectHome: %s\n"
"%sProtectSystem: %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->private_devices),
prefix, protect_home_to_string(c->protect_home),
prefix, protect_system_to_string(c->protect_system),
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->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: "RLIM_FMT"\n",
prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
if (c->ioprio_set) {
_cleanup_free_ char *class_str = NULL;
ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
fprintf(f,
"%sIOSchedulingClass: %s\n"
"%sIOPriority: %i\n",
prefix, strna(class_str),
prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
}
if (c->cpu_sched_set) {
_cleanup_free_ char *policy_str = NULL;
sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
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));
}
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_INFINITY)
fprintf(f, "%sTimerSlackNSec: "NSEC_FMT "\n", prefix, 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) {
_cleanup_free_ char *fac_str = NULL, *lvl_str = NULL;
log_facility_unshifted_to_string_alloc(c->syslog_priority >> 3, &fac_str);
log_level_to_string_alloc(LOG_PRI(c->syslog_priority), &lvl_str);
fprintf(f,
"%sSyslogFacility: %s\n"
"%sSyslogLevel: %s\n",
prefix, strna(fac_str),
prefix, strna(lvl_str));
}
if (c->capabilities) {
_cleanup_cap_free_charp_ char *t;
t = cap_to_text(c->capabilities, NULL);
if (t)
fprintf(f, "%sCapabilities: %s\n", prefix, 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)))
fprintf(f, " %s", strna(capability_to_name(l)));
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);
if (c->selinux_context)
fprintf(f,
"%sSELinuxContext: %s%s\n",
prefix, c->selinux_context_ignore ? "-" : "", c->selinux_context);
if (c->personality != PERSONALITY_INVALID)
fprintf(f,
"%sPersonality: %s\n",
prefix, strna(personality_to_string(c->personality)));
if (c->syscall_filter) {
#ifdef HAVE_SECCOMP
Iterator j;
void *id;
bool first = true;
#endif
fprintf(f,
"%sSystemCallFilter: ",
prefix);
if (!c->syscall_whitelist)
fputc('~', f);
#ifdef HAVE_SECCOMP
SET_FOREACH(id, c->syscall_filter, j) {
_cleanup_free_ char *name = NULL;
if (first)
first = false;
else
fputc(' ', f);
name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
fputs(strna(name), f);
}
#endif
fputc('\n', f);
}
if (c->syscall_archs) {
#ifdef HAVE_SECCOMP
Iterator j;
void *id;
#endif
fprintf(f,
"%sSystemCallArchitectures:",
prefix);
#ifdef HAVE_SECCOMP
SET_FOREACH(id, c->syscall_archs, j)
fprintf(f, " %s", strna(seccomp_arch_to_string(PTR_TO_UINT32(id) - 1)));
#endif
fputc('\n', f);
}
if (c->syscall_errno != 0)
fprintf(f,
"%sSystemCallErrorNumber: %s\n",
prefix, strna(errno_to_name(c->syscall_errno)));
if (c->apparmor_profile)
fprintf(f,
"%sAppArmorProfile: %s%s\n",
prefix, c->apparmor_profile_ignore ? "-" : "", c->apparmor_profile);
}
bool exec_context_maintains_privileges(ExecContext *c) {
assert(c);
/* Returns true if the process forked off would run run under
* an unchanged UID or as root. */
if (!c->user)
return true;
if (streq(c->user, "root") || streq(c->user, "0"))
return true;
return false;
}
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 (s->pid <= 0)
return;
prefix = strempty(prefix);
fprintf(f,
"%sPID: "PID_FMT"\n",
prefix, 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) {
_cleanup_free_ char *cmd = NULL;
const char *prefix2;
assert(c);
assert(f);
prefix = strempty(prefix);
prefix2 = strjoina(prefix, "\t");
cmd = exec_command_line(c->argv);
fprintf(f,
"%sCommand Line: %s\n",
prefix, cmd ? cmd : strerror(ENOMEM));
exec_status_dump(&c->exec_status, f, prefix2);
}
void exec_command_dump_list(ExecCommand *c, FILE *f, const char *prefix) {
assert(f);
prefix = strempty(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;
}
int exec_command_append(ExecCommand *c, const char *path, ...) {
_cleanup_strv_free_ char **l = NULL;
va_list ap;
int r;
assert(c);
assert(path);
va_start(ap, path);
l = strv_new_ap(path, ap);
va_end(ap);
if (!l)
return -ENOMEM;
r = strv_extend_strv(&c->argv, l);
if (r < 0)
return r;
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)
return NULL;
free(r->tmp_dir);
free(r->var_tmp_dir);
safe_close_pair(r->netns_storage_socket);
free(r);
return NULL;
}
int exec_runtime_serialize(Unit *u, ExecRuntime *rt, 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(Unit *u, ExecRuntime **rt, 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 log_oom();
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 log_oom();
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 log_oom();
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse netns socket value: %s", value);
else {
safe_close((*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 log_oom();
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_unit_debug(u, "Failed to parse netns socket value: %s", value);
else {
safe_close((*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;
(void) rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL);
return NULL;
}
void exec_runtime_destroy(ExecRuntime *rt) {
int r;
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);
r = asynchronous_job(remove_tmpdir_thread, rt->tmp_dir);
if (r < 0) {
log_warning_errno(r, "Failed to nuke %s: %m", rt->tmp_dir);
free(rt->tmp_dir);
}
rt->tmp_dir = NULL;
}
if (rt->var_tmp_dir) {
log_debug("Spawning thread to nuke %s", rt->var_tmp_dir);
r = asynchronous_job(remove_tmpdir_thread, rt->var_tmp_dir);
if (r < 0) {
log_warning_errno(r, "Failed to nuke %s: %m", rt->var_tmp_dir);
free(rt->var_tmp_dir);
}
rt->var_tmp_dir = NULL;
}
safe_close_pair(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);
static const char* const exec_utmp_mode_table[_EXEC_UTMP_MODE_MAX] = {
[EXEC_UTMP_INIT] = "init",
[EXEC_UTMP_LOGIN] = "login",
[EXEC_UTMP_USER] = "user",
};
DEFINE_STRING_TABLE_LOOKUP(exec_utmp_mode, ExecUtmpMode);