execute.c revision 039f0e70a0fcd71dcf7cc2f3ba2cea2e3b186a60
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 <assert.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <dirent.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <errno.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <fcntl.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <unistd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <string.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <signal.h>
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#include <sys/socket.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <sys/un.h>
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering#include <sys/prctl.h>
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering#include <linux/sched.h>
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include <sys/types.h>
eef46c372f64f40dd75415b2c504c73138719c8dLennart Poettering#include <sys/stat.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <grp.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <pwd.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/mount.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <linux/fs.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <linux/oom.h>
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include <sys/poll.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <glob.h>
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#include <sys/personality.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <libgen.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#undef basename
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_PAM
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering#include <security/pam_appl.h>
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering#endif
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering#ifdef HAVE_SELINUX
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include <selinux/selinux.h>
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#endif
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#ifdef HAVE_SECCOMP
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#include <seccomp.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#ifdef HAVE_APPARMOR
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include <sys/apparmor.h>
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#endif
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "execute.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "strv.h"
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering#include "macro.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering#include "capability.h"
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include "util.h"
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering#include "log.h"
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#include "sd-messages.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "ioprio.h"
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering#include "securebits.h"
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering#include "namespace.h"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#include "exit-status.h"
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering#include "missing.h"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#include "utmp-wtmp.h"
1ee306e1248866617c96ed9f4263f375588ad838Lennart 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"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "mkdir.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "apparmor-util.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "smack-util.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "bus-endpoint.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "label.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "cap-list.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#ifdef HAVE_SECCOMP
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#include "seccomp-util.h"
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#endif
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#define IDLE_TIMEOUT_USEC (5*USEC_PER_SEC)
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering#define IDLE_TIMEOUT2_USEC (1*USEC_PER_SEC)
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering/* This assumes there is a 'tty' group */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering#define TTY_MODE 0620
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering#define SNDBUF_SIZE (8*1024*1024)
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poetteringstatic int shift_fds(int fds[], unsigned n_fds) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering int start, restart_from;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (n_fds <= 0)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return 0;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* Modifies the fds array! (sorts it) */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering assert(fds);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering start = 0;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering for (;;) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering int i;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering restart_from = -1;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering for (i = start; i < (int) n_fds; i++) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering int nfd;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* Already at right index? */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (fds[i] == i+3)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen continue;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if ((nfd = fcntl(fds[i], F_DUPFD, i+3)) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering safe_close(fds[i]);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering fds[i] = nfd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Hmm, the fd we wanted isn't free? Then
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * let's remember that and try again from here */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (nfd != i+3 && restart_from < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen restart_from = i;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (restart_from < 0)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen break;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering start = restart_from;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic int flags_fds(const int fds[], unsigned n_fds, bool nonblock) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen unsigned i;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (n_fds <= 0)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return 0;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering assert(fds);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Drops/Sets O_NONBLOCK and FD_CLOEXEC from the file flags */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering for (i = 0; i < n_fds; i++) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if ((r = fd_nonblock(fds[i], nonblock)) < 0)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return r;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering /* We unconditionally drop FD_CLOEXEC from the fds,
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering * since after all we want to pass these fds to our
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering * children */
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if ((r = fd_cloexec(fds[i], false)) < 0)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return r;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering }
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return 0;
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering}
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_pure_ static const char *tty_path(const ExecContext *context) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert(context);
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (context->tty_path)
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return context->tty_path;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering return "/dev/console";
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poetteringstatic void exec_context_tty_reset(const ExecContext *context) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering assert(context);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (context->tty_vhangup)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering terminal_vhangup(tty_path(context));
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (context->tty_reset)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering reset_terminal(tty_path(context));
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering if (context->tty_vt_disallocate && context->tty_path)
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering vt_disallocate(context->tty_path);
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering}
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersenstatic bool is_terminal_output(ExecOutput o) {
0b63e2789f984e84f40bf6e49f5da15c87298cedLennart Poettering return
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o == EXEC_OUTPUT_TTY ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o == EXEC_OUTPUT_SYSLOG_AND_CONSOLE ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o == EXEC_OUTPUT_KMSG_AND_CONSOLE ||
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering o == EXEC_OUTPUT_JOURNAL_AND_CONSOLE;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int open_null_as(int flags, int nfd) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int fd, r;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert(nfd >= 0);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fd = open("/dev/null", flags|O_NOCTTY);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (fd < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (fd != nfd) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering safe_close(fd);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering } else
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = nfd;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return r;
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering int fd, r;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering union sockaddr_union sa = {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering .un.sun_family = AF_UNIX,
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering .un.sun_path = "/run/systemd/journal/stdout",
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering };
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert(context);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering assert(output < _EXEC_OUTPUT_MAX);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(ident);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering assert(nfd >= 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fd = socket(AF_UNIX, SOCK_STREAM, 0);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (fd < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart 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 safe_close(fd);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (shutdown(fd, SHUT_RD) < 0) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering safe_close(fd);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return -errno;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering fd_inc_sndbuf(fd, SNDBUF_SIZE);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering dprintf(fd,
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering "%s\n"
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering "%s\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "%i\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "%i\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "%i\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "%i\n"
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering "%i\n",
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering context->syslog_identifier ? context->syslog_identifier : ident,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering unit_id,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering context->syslog_priority,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering !!context->syslog_level_prefix,
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering output == EXEC_OUTPUT_SYSLOG || output == EXEC_OUTPUT_SYSLOG_AND_CONSOLE,
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering output == EXEC_OUTPUT_KMSG || output == EXEC_OUTPUT_KMSG_AND_CONSOLE,
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering is_terminal_output(output));
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (fd != nfd) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering safe_close(fd);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering } else
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering r = nfd;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return r;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int open_terminal_as(const char *path, mode_t mode, int nfd) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering int fd, r;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert(path);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering assert(nfd >= 0);
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if ((fd = open_terminal(path, mode | O_NOCTTY)) < 0)
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return fd;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering if (fd != nfd) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering r = dup2(fd, nfd) < 0 ? -errno : nfd;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering safe_close(fd);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering } else
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering r = nfd;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return r;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poetteringstatic bool is_terminal_input(ExecInput i) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering i == EXEC_INPUT_TTY ||
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering i == EXEC_INPUT_TTY_FORCE ||
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering i == EXEC_INPUT_TTY_FAIL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int fixup_input(ExecInput std_input, int socket_fd, bool apply_tty_stdin) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (is_terminal_input(std_input) && !apply_tty_stdin)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return EXEC_INPUT_NULL;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering return EXEC_INPUT_NULL;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return std_input;
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering}
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poetteringstatic int fixup_output(ExecOutput std_output, int socket_fd) {
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return EXEC_OUTPUT_INHERIT;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
10f9c75519671e7c7ab8993b54fe22da7c2d0c38Lennart Poettering return std_output;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering}
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poetteringstatic int setup_input(const ExecContext *context, int socket_fd, bool apply_tty_stdin) {
8937e7b68940d0fa0d0aab90eb7425fa7dccebc9Lennart Poettering ExecInput i;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering assert(context);
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering switch (i) {
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering case EXEC_INPUT_NULL:
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering return open_null_as(O_RDONLY, STDIN_FILENO);
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering case EXEC_INPUT_TTY:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering case EXEC_INPUT_TTY_FORCE:
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen case EXEC_INPUT_TTY_FAIL: {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int fd, r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering fd = acquire_terminal(tty_path(context),
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering i == EXEC_INPUT_TTY_FAIL,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering i == EXEC_INPUT_TTY_FORCE,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering false,
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering USEC_INFINITY);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (fd < 0)
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering return fd;
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering if (fd != STDIN_FILENO) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = dup2(fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering safe_close(fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering } else
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering r = STDIN_FILENO;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return r;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering case EXEC_INPUT_SOCKET:
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return dup2(socket_fd, STDIN_FILENO) < 0 ? -errno : STDIN_FILENO;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering default:
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen assert_not_reached("Unknown input type");
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering }
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poetteringstatic int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) {
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering ExecOutput o;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering ExecInput i;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering int r;
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering assert(context);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering assert(ident);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering i = fixup_input(context->std_input, socket_fd, apply_tty_stdin);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering o = fixup_output(context->std_output, socket_fd);
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering if (fileno == STDERR_FILENO) {
9d12709626bccc0cae677a7035f62efe6aabb4abLennart Poettering ExecOutput e;
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering e = fixup_output(context->std_error, socket_fd);
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* This expects the input and output are already set up */
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering /* Don't change the stderr file descriptor if we inherit all
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering * the way and are not on a tty */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (e == EXEC_OUTPUT_INHERIT &&
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering o == EXEC_OUTPUT_INHERIT &&
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering i == EXEC_INPUT_NULL &&
aa1936ea1a89c2bb968ba33e3274898a4eeae771Lennart Poettering !is_terminal_input(context->std_input) &&
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering getppid () != 1)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* Duplicate from stdout if possible */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (e == o || e == EXEC_OUTPUT_INHERIT)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dup2(STDOUT_FILENO, fileno) < 0 ? -errno : fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering o = e;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering } else if (o == EXEC_OUTPUT_INHERIT) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* If input got downgraded, inherit the original value */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (i == EXEC_INPUT_NULL && is_terminal_input(context->std_input))
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, fileno);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* If the input is connected to anything that's not a /dev/null, inherit that... */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (i != EXEC_INPUT_NULL)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* If we are not started from PID 1 we just inherit STDOUT from our parent process. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (getppid() != 1)
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering return fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* We need to open /dev/null here anew, to get the right access mode. */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return open_null_as(O_WRONLY, fileno);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering }
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering switch (o) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_OUTPUT_NULL:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return open_null_as(O_WRONLY, fileno);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_OUTPUT_TTY:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (is_terminal_input(i))
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dup2(STDIN_FILENO, fileno) < 0 ? -errno : fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering /* We don't reset the terminal if this is just about output */
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return open_terminal_as(tty_path(context), O_WRONLY, fileno);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case EXEC_OUTPUT_SYSLOG:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case EXEC_OUTPUT_SYSLOG_AND_CONSOLE:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case EXEC_OUTPUT_KMSG:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case EXEC_OUTPUT_KMSG_AND_CONSOLE:
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering case EXEC_OUTPUT_JOURNAL:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_OUTPUT_JOURNAL_AND_CONSOLE:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = connect_logger_as(context, o, ident, unit_id, fileno);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0) {
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering log_unit_struct(unit_id,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LOG_CRIT,
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LOG_MESSAGE("Failed to connect %s of %s to the journal socket: %s",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering fileno == STDOUT_FILENO ? "stdout" : "stderr",
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering unit_id, strerror(-r)),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering LOG_ERRNO(-r),
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering NULL);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering r = open_null_as(O_WRONLY, fileno);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering }
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering case EXEC_OUTPUT_SOCKET:
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering assert(socket_fd >= 0);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return dup2(socket_fd, fileno) < 0 ? -errno : fileno;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering default:
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert_not_reached("Unknown error type");
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int chown_terminal(int fd, uid_t uid) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering struct stat st;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(fd >= 0);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering /* This might fail. What matters are the results. */
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering (void) fchown(fd, uid, -1);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering (void) fchmod(fd, TTY_MODE);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (fstat(fd, &st) < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return -errno;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (st.st_uid != uid || (st.st_mode & 0777) != TTY_MODE)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return -EPERM;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return 0;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering}
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poetteringstatic int setup_confirm_stdio(int *_saved_stdin,
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int *_saved_stdout) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering int fd = -1, saved_stdin, saved_stdout = -1, r;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(_saved_stdin);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering assert(_saved_stdout);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering saved_stdin = fcntl(STDIN_FILENO, F_DUPFD, 3);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (saved_stdin < 0)
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering return -errno;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering saved_stdout = fcntl(STDOUT_FILENO, F_DUPFD, 3);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (saved_stdout < 0) {
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering r = errno;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering goto fail;
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering }
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering fd = acquire_terminal(
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering "/dev/console",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering false,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers false,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering false,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers DEFAULT_CONFIRM_USEC);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (fd < 0) {
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = fd;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = chown_terminal(fd, getuid());
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (dup2(fd, STDIN_FILENO) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (dup2(fd, STDOUT_FILENO) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto fail;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fd >= 2)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *_saved_stdin = saved_stdin;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering *_saved_stdout = saved_stdout;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringfail:
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(saved_stdout);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(saved_stdin);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering safe_close(fd);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering_printf_(1, 2) static int write_confirm_message(const char *format, ...) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_close_ int fd = -1;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return fd;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_start(ap, format);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering vdprintf(fd, format, ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering va_end(ap);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringstatic int restore_confirm_stdio(int *saved_stdin,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int *saved_stdout) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(saved_stdin);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering assert(saved_stdout);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering release_terminal();
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (*saved_stdin >= 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (dup2(*saved_stdin, STDIN_FILENO) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (*saved_stdout >= 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (dup2(*saved_stdout, STDOUT_FILENO) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering safe_close(*saved_stdin);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering safe_close(*saved_stdout);
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poetteringstatic int ask_for_confirmation(char *response, char **argv) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering int saved_stdout = -1, saved_stdin = -1, r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering _cleanup_free_ char *line = NULL;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering r = setup_confirm_stdio(&saved_stdin, &saved_stdout);
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering if (r < 0)
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering return r;
878cd7e95ca303f9851d227a22d2022bd49944b0Lennart Poettering
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering line = exec_command_line(argv);
717603e391b52983ca1fd218e7333a1b9dfc5c05Lennart Poettering if (!line)
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering return -ENOMEM;
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering r = ask_char(response, "yns", "Execute %s? [Yes, No, Skip] ", line);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering restore_confirm_stdio(&saved_stdin, &saved_stdout);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return r;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering}
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poetteringstatic int enforce_groups(const ExecContext *context, const char *username, gid_t gid) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering bool keep_groups = false;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering int r;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering assert(context);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering /* Lookup and set GID and supplementary group list. Here too
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering * we avoid NSS lookups for gid=0. */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (context->group || username) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (context->group) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *g = context->group;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if ((r = get_group_creds(&g, &gid)) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return r;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* First step, initialize groups from /etc/groups */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (username && gid != 0) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (initgroups(username, gid) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek keep_groups = true;
e7e9b6bb0b0bc5b1eb256a44f8afec6b634f26efZbigniew Jędrzejewski-Szmek }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering /* Second step, set our gids */
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (setresgid(gid, gid, gid) < 0)
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering return -errno;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering }
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering if (context->supplementary_groups) {
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering int ngroups_max, k;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering gid_t *gids;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char **i;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* Final step, initialize any manually set supplementary groups */
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering assert_se((ngroups_max = (int) sysconf(_SC_NGROUPS_MAX)) > 0);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (!(gids = new(gid_t, ngroups_max)))
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return -ENOMEM;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (keep_groups) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if ((k = getgroups(ngroups_max, gids)) < 0) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering free(gids);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return -errno;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers } else
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers k = 0;
a6c616024db23fef34152c1432892824a07799ccLennart Poettering
a6c616024db23fef34152c1432892824a07799ccLennart Poettering STRV_FOREACH(i, context->supplementary_groups) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const char *g;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (k >= ngroups_max) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering free(gids);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -E2BIG;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers g = *i;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers r = get_group_creds(&g, gids+k);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers if (r < 0) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers free(gids);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return r;
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt }
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering k++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (setgroups(k, gids) < 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(gids);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers free(gids);
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers }
89f7c8465cd1ab37347dd0c15920bce31e8225dfLennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers return 0;
f48e75cb9a8112d35855c44a156934f2ee0edb2eLennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sieversstatic int enforce_user(const ExecContext *context, uid_t uid) {
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers assert(context);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Sets (but doesn't lookup) the uid and make sure we keep the
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers * capabilities while doing so. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (context->capabilities) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering _cleanup_cap_free_ cap_t d = NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering static const cap_value_t bits[] = {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering CAP_SETUID, /* Necessary so that we can run setresuid() below */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers CAP_SETPCAP /* Necessary so that we can set PR_SET_SECUREBITS later on */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers };
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers /* First step: If we need to keep capabilities but
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen * drop privileges we need to make sure we keep our
27e72d6b22890ba4a8cbc05c49667cd1cccf1461Simon Peeters * caps, while we drop privileges. */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen if (uid != 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt int sb = context->secure_bits | 1<<SECURE_KEEP_CAPS;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (prctl(PR_GET_SECUREBITS) != sb)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (prctl(PR_SET_SECUREBITS, sb) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* Second step: set the capabilities. This will reduce
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * the capabilities to the minimum we need. */
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering d = cap_dup(context->capabilities);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (!d)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cap_set_flag(d, CAP_EFFECTIVE, ELEMENTSOF(bits), bits, CAP_SET) < 0 ||
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering cap_set_flag(d, CAP_PERMITTED, ELEMENTSOF(bits), bits, CAP_SET) < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -errno;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (cap_set_proc(d) < 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return -errno;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Third step: actually set the uids */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (setresuid(uid, uid, uid) < 0)
8c841f21f5042b11acc91cc1b039cb162cbbe8f4Djalal Harouni return -errno;
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* At this point we should have all necessary capabilities but
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering are otherwise a normal user. However, the caps might got
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering corrupted due to the setresuid() so we need clean them up
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering later. This is done outside of this call. */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return 0;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen#ifdef HAVE_PAM
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int null_conv(
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen int num_msg,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen const struct pam_message **msg,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering struct pam_response **resp,
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen void *appdata_ptr) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen /* We don't support conversations */
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen return PAM_CONV_ERR;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen}
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poettering
5b30bef856e89a571df57b7b953e9a1409d9acedLennart Poetteringstatic int setup_pam(
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *name,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers const char *user,
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering uid_t uid,
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers 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 ss, old_ss;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int pam_code = PAM_SUCCESS;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int err;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char **e = NULL;
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering bool close_session = false;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering pid_t pam_pid = 0, parent_pid;
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering int flags = 0;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart 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
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * will then stay around until killed via PR_GET_PDEATHSIG or
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart 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_PRI(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) {
9a14fb6285bdb089d4fc195410de3362cb4f586fThomas Hindoe Paaboel Andersen 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;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart 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
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering e = pam_getenvlist(handle);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (!e) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = PAM_BUF_ERR;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering }
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering /* Block SIGTERM, so that we know that it won't get lost in
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * the child */
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering if (sigemptyset(&ss) < 0 ||
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering sigaddset(&ss, SIGTERM) < 0 ||
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering sigprocmask(SIG_BLOCK, &ss, &old_ss) < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering goto fail;
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering parent_pid = getpid();
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering pam_pid = fork();
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering if (pam_pid < 0)
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_pid == 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int sig;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering int r = EXIT_PAM;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* The child's job is to reset the PAM session on
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * termination */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* This string must fit in 10 chars (i.e. the length
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering * of "/sbin/init"), to look pretty in /bin/ps */
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering rename_process("(sd-pam)");
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering /* Make sure we don't keep open the passed fds in this
c19de71113f956809995fc68817e055e9f61f607Lennart Poettering child. We assume that otherwise only those fds are
b6b1849830f5e4a6065c3b0c993668e500c954d3Lennart Poettering open here that have been opened by PAM. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering close_many(fds, n_fds);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Drop privileges - we don't need any to pam_close_session
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * and this will make PR_SET_PDEATHSIG work in most cases.
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * If this fails, ignore the error - but expect sd-pam threads
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * to fail to exit normally */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (setresuid(uid, uid, uid) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_error_errno(r, "Error: Failed to setresuid() in sd-pam: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Wait until our parent died. This will only work if
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * the above setresuid() succeeds, otherwise the kernel
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * will not allow unprivileged parents kill their privileged
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * children this way. We rely on the control groups kill logic
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * to do the rest for us. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (prctl(PR_SET_PDEATHSIG, SIGTERM) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto child_finish;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Check if our parent process might already have
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * died? */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (getppid() == parent_pid) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering for (;;) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (sigwait(&ss, &sig) < 0) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (errno == EINTR)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering continue;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto child_finish;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering assert(sig == SIGTERM);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering break;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* If our parent died we'll end the session */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (getppid() != parent_pid) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_close_session(handle, flags);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto child_finish;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering r = 0;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering child_finish:
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_end(handle, pam_code | flags);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering _exit(r);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* If the child was forked off successfully it will do all the
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * cleanups, so forget about the handle here. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering handle = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* Unblock SIGTERM again in the parent */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (sigprocmask(SIG_SETMASK, &old_ss, NULL) < 0)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering goto fail;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* We close the log explicitly here, since the PAM modules
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * might have opened it, but we don't want this fd around. */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering closelog();
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering *pam_env = e;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering e = NULL;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return 0;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringfail:
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (pam_code != PAM_SUCCESS) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_error("PAM failed: %s", pam_strerror(handle, pam_code));
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering err = -EPERM; /* PAM errors do not map to errno */
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering } else {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering log_error_errno(errno, "PAM failed: %m");
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering err = -errno;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (handle) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering if (close_session)
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_code = pam_close_session(handle, flags);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering pam_end(handle, pam_code | flags);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering strv_free(e);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering closelog();
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (pam_pid > 1) {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering kill(pam_pid, SIGTERM);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering kill(pam_pid, SIGCONT);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering return err;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering}
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering#endif
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poetteringstatic void rename_process_from_path(const char *path) {
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering char process_name[11];
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering const char *p;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering size_t l;
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering /* This resulting string must fit in 10 chars (i.e. the length
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * of "/sbin/init") to look pretty in /bin/ps */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
9f6eb1cd58f2ddf2eb6ba0e4de056e13d938af75Kay Sievers p = basename(path);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (isempty(p)) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering rename_process("(...)");
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering l = strlen(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (l > 8) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering /* The end of the process name is usually more
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering * interesting, since the first bit might just be
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering * "systemd-" */
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering p = p + l - 8;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering l = 8;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering process_name[0] = '(';
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen memcpy(process_name+1, p, l);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering process_name[1+l] = ')';
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering process_name[1+l+1] = 0;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering rename_process(process_name);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering}
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering#ifdef HAVE_SECCOMP
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersenstatic int apply_seccomp(const ExecContext *c) {
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen uint32_t negative_action, action;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering scmp_filter_ctx *seccomp;
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen Iterator i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering void *id;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int r;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(c);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering negative_action = c->syscall_errno == 0 ? SCMP_ACT_KILL : SCMP_ACT_ERRNO(c->syscall_errno);
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering seccomp = seccomp_init(c->syscall_whitelist ? negative_action : SCMP_ACT_ALLOW);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!seccomp)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering return -ENOMEM;
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (c->syscall_archs) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering SET_FOREACH(id, c->syscall_archs, i) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = seccomp_arch_add(seccomp, PTR_TO_UINT32(id) - 1);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == -EEXIST)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering continue;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r < 0)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering goto finish;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering } else {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering r = seccomp_add_secondary_archs(seccomp);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (r < 0)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering goto finish;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering action = c->syscall_whitelist ? SCMP_ACT_ALLOW : negative_action;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering SET_FOREACH(id, c->syscall_filter, i) {
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = seccomp_rule_add(seccomp, action, PTR_TO_INT(id) - 1, 0);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (r < 0)
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering goto finish;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering }
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering if (r < 0)
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering goto finish;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering r = seccomp_load(seccomp);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poetteringfinish:
1dba654b27918c22e413ac5b3c19301f1ff86ad2Lennart Poettering seccomp_release(seccomp);
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering return r;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering}
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poetteringstatic int apply_address_families(const ExecContext *c) {
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering scmp_filter_ctx *seccomp;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering Iterator i;
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering int r;
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert(c);
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering seccomp = seccomp_init(SCMP_ACT_ALLOW);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (!seccomp)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return -ENOMEM;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering r = seccomp_add_secondary_archs(seccomp);
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering if (r < 0)
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (c->address_families_whitelist) {
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering int af, first = 0, last = 0;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering void *afp;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering /* If this is a whitelist, we first block the address
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering * families that are out of range and then everything
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering * that is not in the set. First, we find the lowest
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering * and highest address family in the set. */
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering SET_FOREACH(afp, c->address_families, i) {
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering af = PTR_TO_INT(afp);
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
0370612e0522191f929e3feb7d4937fff3d421e2Lennart Poettering if (af <= 0 || af >= af_max())
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering continue;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (first == 0 || af < first)
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering first = af;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (last == 0 || af > last)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering last = af;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering assert((first == 0) == (last == 0));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (first == 0) {
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering /* No entries in the valid range, block everything */
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = seccomp_rule_add(
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering seccomp,
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering SCMP_SYS(socket),
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering 0);
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering if (r < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering goto finish;
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering } else {
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering /* Block everything below the first entry */
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering r = seccomp_rule_add(
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering seccomp,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering SCMP_SYS(socket),
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering 1,
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering SCMP_A0(SCMP_CMP_LT, first));
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (r < 0)
90adaa25e894a580930ef2c3e65ab8db8295515aLennart Poettering goto finish;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* Block everything above the last entry */
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = seccomp_rule_add(
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering seccomp,
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_SYS(socket),
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering 1,
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_A0(SCMP_CMP_GT, last));
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (r < 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering goto finish;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering /* Block everything between the first and last
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering * entry */
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering for (af = 1; af < af_max(); af++) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering if (set_contains(c->address_families, INT_TO_PTR(af)))
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering continue;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering r = seccomp_rule_add(
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering seccomp,
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_SYS(socket),
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering 1,
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering SCMP_A0(SCMP_CMP_EQ, af));
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (r < 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering goto finish;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering }
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering } else {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering void *af;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering /* If this is a blacklist, then generate one rule for
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering * each address family that are then combined in OR
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering * checks. */
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering SET_FOREACH(af, c->address_families, i) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = seccomp_rule_add(
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering seccomp,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering SCMP_ACT_ERRNO(EPROTONOSUPPORT),
bf441e3d9371a7e5aa1def66cfc40f0118884644Lennart Poettering SCMP_SYS(socket),
de33fc625725d199629ed074d6278504deb23debLennart Poettering 1,
923d8fd381bced1c2d90ca53d18629d61a0f454aLennart Poettering SCMP_A0(SCMP_CMP_EQ, PTR_TO_INT(af)));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (r < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering goto finish;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering }
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (r < 0)
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt goto finish;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering r = seccomp_load(seccomp);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidtfinish:
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering seccomp_release(seccomp);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering return r;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering}
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering#endif
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poetteringstatic void do_idle_pipe_dance(int idle_pipe[4]) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering assert(idle_pipe);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering safe_close(idle_pipe[1]);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering safe_close(idle_pipe[2]);
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (idle_pipe[0] >= 0) {
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering int r;
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering r = fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT_USEC);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering if (idle_pipe[3] >= 0 && r == 0 /* timeout */) {
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering /* Signal systemd that we are bored and want to continue. */
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering write(idle_pipe[3], "x", 1);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering /* Wait for systemd to react to the signal above. */
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering fd_wait_for_event(idle_pipe[0], POLLHUP, IDLE_TIMEOUT2_USEC);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering }
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering safe_close(idle_pipe[0]);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering }
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering safe_close(idle_pipe[3]);
d04c1fb8e215600b4950c6778c6c16ddafc14024Lennart Poettering}
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering
40205d706e1210763ff4c98a317556375bd04bcdLennart Poetteringstatic int build_environment(
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering const ExecContext *c,
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering unsigned n_fds,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t watchdog_usec,
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering const char *home,
40205d706e1210763ff4c98a317556375bd04bcdLennart Poettering const char *username,
ee451d766a64117a41ec36dd71e61683c9d9b83cLennart Poettering const char *shell,
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char ***ret) {
813c65c34beae2eed1f93d9317f97d7e806389f5Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering _cleanup_strv_free_ char **our_env = NULL;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering unsigned n_env = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering char *x;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(c);
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering assert(ret);
9b15b7846d4de01bb5d9700a24077787e984e8abLennart Poettering
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt our_env = new0(char*, 10);
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (!our_env)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return -ENOMEM;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (n_fds > 0) {
f647962d64e844689f3e2acfce6102fc47e76df2Michal Schmidt if (asprintf(&x, "LISTEN_PID="PID_FMT, getpid()) < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -ENOMEM;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env[n_env++] = x;
da054c3782f25b3b18243f6c76dcfcf90ba70274Lennart Poettering
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering if (asprintf(&x, "LISTEN_FDS=%u", n_fds) < 0)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return -ENOMEM;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering our_env[n_env++] = x;
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering }
c7b7d4493aa03e9ef5fb1e670b8969a48aa494ddLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (watchdog_usec > 0) {
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering if (asprintf(&x, "WATCHDOG_PID="PID_FMT, getpid()) < 0)
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering return -ENOMEM;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering our_env[n_env++] = x;
0ec5543c4c0318552a4dcdd83210793347b93081Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (asprintf(&x, "WATCHDOG_USEC="USEC_FMT, watchdog_usec) < 0)
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering return -ENOMEM;
023fb90b83871a15ef7f57e8cd126e3426f99b9eLennart Poettering our_env[n_env++] = x;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (home) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering x = strappend("HOME=", home);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (!x)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return -ENOMEM;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering our_env[n_env++] = x;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering if (username) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering x = strappend("LOGNAME=", username);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (!x)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -ENOMEM;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering our_env[n_env++] = x;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering x = strappend("USER=", username);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (!x)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -ENOMEM;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering our_env[n_env++] = x;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (shell) {
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering x = strappend("SHELL=", shell);
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (!x)
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering return -ENOMEM;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering our_env[n_env++] = x;
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering if (is_terminal_input(c->std_input) ||
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering c->std_output == EXEC_OUTPUT_TTY ||
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering c->std_error == EXEC_OUTPUT_TTY ||
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering c->tty_path) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering x = strdup(default_term_for_tty(tty_path(c)));
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (!x)
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering return -ENOMEM;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering our_env[n_env++] = x;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering our_env[n_env++] = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(n_env <= 10);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *ret = our_env;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering our_env = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering}
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poetteringstatic int exec_child(ExecCommand *command,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering const ExecContext *context,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering const ExecParameters *params,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering ExecRuntime *runtime,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering char **argv,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int socket_fd,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int *fds, unsigned n_fds,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering char **files_env,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int *error) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering _cleanup_strv_free_ char **our_env = NULL, **pam_env = NULL, **final_env = NULL, **final_argv = NULL;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering _cleanup_free_ char *mac_selinux_context_net = NULL;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering const char *username = NULL, *home = NULL, *shell = NULL;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering unsigned n_dont_close = 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int dont_close[n_fds + 4];
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering uid_t uid = UID_INVALID;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering gid_t gid = GID_INVALID;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering int i, err;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(command);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(context);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(params);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering assert(error);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering rename_process_from_path(command->path);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* We reset exactly these signals, since they are the
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * only ones we set to SIG_IGN in the main daemon. All
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * others we leave untouched because we set them to
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * SIG_DFL or a valid handler initially, both of which
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * will be demoted to SIG_DFL. */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering default_signals(SIGNALS_CRASH_HANDLER,
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering SIGNALS_IGNORE, -1);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (context->ignore_sigpipe)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering ignore_signals(SIGPIPE, -1);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering err = reset_signal_mask();
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (err < 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering *error = EXIT_SIGNAL_MASK;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return err;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering if (params->idle_pipe)
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering do_idle_pipe_dance(params->idle_pipe);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* Close sockets very early to make sure we don't
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * block init reexecution because it cannot bind its
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * sockets */
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering log_forget_fds();
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (socket_fd >= 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering dont_close[n_dont_close++] = socket_fd;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (n_fds > 0) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering memcpy(dont_close + n_dont_close, fds, sizeof(int) * n_fds);
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering n_dont_close += n_fds;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering }
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (params->bus_endpoint_fd >= 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering dont_close[n_dont_close++] = params->bus_endpoint_fd;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (runtime) {
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering if (runtime->netns_storage_socket[0] >= 0)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[0];
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (runtime->netns_storage_socket[1] >= 0)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering dont_close[n_dont_close++] = runtime->netns_storage_socket[1];
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering err = close_all_fds(dont_close, n_dont_close);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_FDS;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return err;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering }
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (!context->same_pgrp)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (setsid() < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_SETSID;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -errno;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering exec_context_tty_reset(context);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (params->confirm_spawn) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering char response;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering err = ask_for_confirmation(&response, argv);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err == -ETIMEDOUT)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering write_confirm_message("Confirmation question timed out, assuming positive response.\n");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering else if (err < 0)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering write_confirm_message("Couldn't ask confirmation question, assuming positive response: %s\n", strerror(-err));
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering else if (response == 's') {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering write_confirm_message("Skipping execution.\n");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_CONFIRM;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return -ECANCELED;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering } else if (response == 'n') {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering write_confirm_message("Failing execution.\n");
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = 0;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return 0;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering /* If a socket is connected to STDIN/STDOUT/STDERR, we
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering * must sure to drop O_NONBLOCK */
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (socket_fd >= 0)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering fd_nonblock(socket_fd, false);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering err = setup_input(context, socket_fd, params->apply_tty_stdin);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_STDIN;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return err;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_STDOUT;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return err;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_STDERR;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return err;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (params->cgroup_path) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering err = cg_attach_everywhere(params->cgroup_supported, params->cgroup_path, 0, NULL, NULL);
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (err < 0) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering *error = EXIT_CGROUP;
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering }
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering if (context->oom_score_adjust_set) {
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering char t[16];
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering snprintf(t, sizeof(t), "%i", context->oom_score_adjust);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering char_array_0(t);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (write_string_file("/proc/self/oom_score_adj", t) < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_OOM_ADJUST;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->nice_set)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (setpriority(PRIO_PROCESS, 0, context->nice) < 0) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering *error = EXIT_NICE;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->cpu_sched_set) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering struct sched_param param = {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering .sched_priority = context->cpu_sched_priority,
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering };
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering err = sched_setscheduler(0,
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering context->cpu_sched_policy |
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering (context->cpu_sched_reset_on_fork ?
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering SCHED_RESET_ON_FORK : 0),
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering &param);
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering if (err < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_SETSCHEDULER;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->cpuset)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (sched_setaffinity(0, CPU_ALLOC_SIZE(context->cpuset_ncpus), context->cpuset) < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_CPUAFFINITY;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->ioprio_set)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (ioprio_set(IOPRIO_WHO_PROCESS, 0, context->ioprio) < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_IOPRIO;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->timer_slack_nsec != NSEC_INFINITY)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (prctl(PR_SET_TIMERSLACK, context->timer_slack_nsec) < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_TIMERSLACK;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->personality != 0xffffffffUL)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (personality(context->personality) < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_PERSONALITY;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return -errno;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->utmp_id)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (context->user) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering username = context->user;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering err = get_user_creds(&username, &uid, &gid, &home, &shell);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (err < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_USER;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (is_terminal_input(context->std_input)) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering err = chown_terminal(STDIN_FILENO, uid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (err < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_STDIN;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#ifdef ENABLE_KDBUS
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (params->bus_endpoint_fd >= 0 && context->bus_endpoint) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering uid_t ep_uid = (uid == UID_INVALID) ? 0 : uid;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering err = bus_kernel_set_endpoint_policy(params->bus_endpoint_fd, ep_uid, context->bus_endpoint);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (err < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_BUS_ENDPOINT;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering#endif
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 err = cg_set_task_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0644, uid, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (err < 0) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering *error = EXIT_CGROUP;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering err = cg_set_group_access(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, 0755, uid, gid);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (err < 0) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering *error = EXIT_CGROUP;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return err;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering }
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (!strv_isempty(context->runtime_directory) && params->runtime_prefix) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char **rt;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering STRV_FOREACH(rt, context->runtime_directory) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering _cleanup_free_ char *p;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering p = strjoin(params->runtime_prefix, "/", *rt, NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!p) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering *error = EXIT_RUNTIME_DIRECTORY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -ENOMEM;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = mkdir_safe(p, context->runtime_directory_mode, uid, gid);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_RUNTIME_DIRECTORY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (params->apply_permissions) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = enforce_groups(context, username, gid);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_GROUP;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering umask(context->umask);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#ifdef HAVE_PAM
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (params->apply_permissions && context->pam_name && username) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = setup_pam(context->pam_name, username, uid, context->tty_path, &pam_env, fds, n_fds);
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_PAM;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->private_network && runtime && runtime->netns_storage_socket[0] >= 0) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering err = setup_netns(runtime->netns_storage_socket);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_NETWORK;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering return err;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (!strv_isempty(context->read_write_dirs) ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering !strv_isempty(context->read_only_dirs) ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering !strv_isempty(context->inaccessible_dirs) ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->mount_flags != 0 ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering (context->private_tmp && runtime && (runtime->tmp_dir || runtime->var_tmp_dir)) ||
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø params->bus_endpoint_path ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->private_devices ||
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->protect_system != PROTECT_SYSTEM_NO ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->protect_home != PROTECT_HOME_NO) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char *tmp = NULL, *var = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* The runtime struct only contains the parent
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * of the private /tmp, which is
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * non-accessible to world users. Inside of it
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering * there's a /tmp that is sticky, and that's
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering * the one we want to use here. */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->private_tmp && runtime) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (runtime->tmp_dir)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering tmp = strappenda(runtime->tmp_dir, "/tmp");
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (runtime->var_tmp_dir)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering var = strappenda(runtime->var_tmp_dir, "/tmp");
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering err = setup_namespace(
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->read_write_dirs,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->read_only_dirs,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->inaccessible_dirs,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering tmp,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering var,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering params->bus_endpoint_path,
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering context->private_devices,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->protect_home,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->protect_system,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->mount_flags);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err == -EPERM)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_unit_warning_errno(params->unit_id, err, "Failed to set up file system namespace due to lack of privileges. Execution sandbox will not be in effect: %m");
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering else if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_NAMESPACE;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (params->apply_chroot) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->root_directory)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (chroot(context->root_directory) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_CHROOT;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (chdir(context->working_directory ? context->working_directory : "/") < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_CHDIR;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering } else {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering _cleanup_free_ char *d = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (asprintf(&d, "%s/%s",
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->root_directory ? context->root_directory : "",
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->working_directory ? context->working_directory : "") < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_MEMORY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -ENOMEM;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (chdir(d) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_CHDIR;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering#ifdef HAVE_SELINUX
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (params->apply_permissions && mac_selinux_use() && params->selinux_context_net && socket_fd >= 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = mac_selinux_get_child_mls_label(socket_fd, command->path, context->selinux_context, &mac_selinux_context_net);
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering if (err < 0) {
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering *error = EXIT_SELINUX_CONTEXT;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering return err;
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering }
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6adf7b5e46d32376868feef0197e6ada352aa6f2Lennart Poettering /* We repeat the fd closing here, to make sure that
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * nothing is leaked from the PAM modules. Note that
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * we are more aggressive this time since socket_fd
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * and the netns fds we don't need anymore. The custom
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * endpoint fd was needed to upload the policy and can
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * now be closed as well. */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = close_all_fds(fds, n_fds);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err >= 0)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = shift_fds(fds, n_fds);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err >= 0)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = flags_fds(fds, n_fds, context->non_blocking);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_FDS;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (params->apply_permissions) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering for (i = 0; i < _RLIMIT_MAX; i++) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!context->rlimit[i])
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering continue;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (setrlimit_closest(i, context->rlimit[i]) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_LIMITS;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->capability_bounding_set_drop) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = capability_bounding_set_drop(context->capability_bounding_set_drop, false);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_CAPABILITIES;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#ifdef HAVE_SMACK
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->smack_process_label) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = mac_smack_apply_pid(0, context->smack_process_label);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_SMACK_PROCESS_LABEL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->user) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = enforce_user(context, uid);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_USER;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* PR_GET_SECUREBITS is not privileged, while
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * PR_SET_SECUREBITS is. So to suppress
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * potential EPERMs we'll try not to call
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * PR_SET_SECUREBITS unless necessary. */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (prctl(PR_GET_SECUREBITS) != context->secure_bits)
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering if (prctl(PR_SET_SECUREBITS, context->secure_bits) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_SECUREBITS;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->capabilities)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (cap_set_proc(context->capabilities) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_CAPABILITIES;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->no_new_privileges)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_NO_NEW_PRIVILEGES;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#ifdef HAVE_SECCOMP
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->address_families_whitelist ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering !set_isempty(context->address_families)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = apply_address_families(context);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_ADDRESS_FAMILIES;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->syscall_whitelist ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering !set_isempty(context->syscall_filter) ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering !set_isempty(context->syscall_archs)) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = apply_seccomp(context);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_SECCOMP;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#ifdef HAVE_SELINUX
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (mac_selinux_use()) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char *exec_context = mac_selinux_context_net ?: context->selinux_context;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (exec_context) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = setexeccon(exec_context);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_SELINUX_CONTEXT;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#ifdef HAVE_APPARMOR
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->apparmor_profile && mac_apparmor_use()) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = aa_change_onexec(context->apparmor_profile);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0 && !context->apparmor_profile_ignore) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_APPARMOR_PROFILE;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering#endif
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = build_environment(context, n_fds, params->watchdog_usec, home, username, shell, &our_env);
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_MEMORY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering final_env = strv_env_merge(5,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering params->environment,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering our_env,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->environment,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering files_env,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering pam_env,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!final_env) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_MEMORY;
56e6c2abb8f18bba2bb9d96d66ac7e633349ddfbLennart Poettering return -ENOMEM;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering final_argv = replace_env_argv(argv, final_env);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!final_argv) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_MEMORY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -ENOMEM;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering final_env = strv_env_clean(final_env);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (_unlikely_(log_get_max_level() >= LOG_PRI(LOG_DEBUG))) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering _cleanup_free_ char *line;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering line = exec_command_line(final_argv);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (line) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_open();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_unit_struct(params->unit_id,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_DEBUG,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "EXECUTABLE=%s", command->path,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE("Executing: %s", line),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_close();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering execve(command->path, final_argv, final_env);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *error = EXIT_EXEC;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringint exec_spawn(ExecCommand *command,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering const ExecContext *context,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering const ExecParameters *params,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering ExecRuntime *runtime,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering pid_t *ret) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering _cleanup_strv_free_ char **files_env = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering int *fds = NULL; unsigned n_fds = 0;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char *line, **argv;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering int socket_fd;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering pid_t pid;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering int err;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(command);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(context);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(ret);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(params);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(params->fds || params->n_fds <= 0);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (context->std_input == EXEC_INPUT_SOCKET ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->std_output == EXEC_OUTPUT_SOCKET ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context->std_error == EXEC_OUTPUT_SOCKET) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (params->n_fds != 1)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -EINVAL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering socket_fd = params->fds[0];
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering } else {
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering socket_fd = -1;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fds = params->fds;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering n_fds = params->n_fds;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = exec_context_load_environment(context, params->unit_id, &files_env);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (err < 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_unit_struct(params->unit_id,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_ERR,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE("Failed to load environment files: %s", strerror(-err)),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_ERRNO(-err),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return err;
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering argv = params->argv ?: command->argv;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering line = exec_command_line(argv);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (!line)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return log_oom();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_unit_struct(params->unit_id,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_DEBUG,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "EXECUTABLE=%s", command->path,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE("About to execute: %s", line),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(line);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering pid = fork();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (pid < 0)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return -errno;
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (pid == 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering int r;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering err = exec_child(command,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering context,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering params,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering runtime,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering argv,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering socket_fd,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fds, n_fds,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering files_env,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering &r);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (r != 0) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_open();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_struct(LOG_ERR,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE_ID(SD_MESSAGE_SPAWN_FAILED),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "EXECUTABLE=%s", command->path,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE("Failed at step %s spawning %s: %s",
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering exit_status_to_string(r, EXIT_STATUS_SYSTEMD),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering command->path, strerror(-err)),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_ERRNO(-err),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering NULL);
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering log_close();
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering _exit(r);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering log_unit_struct(params->unit_id,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_DEBUG,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering LOG_MESSAGE("Forked %s as "PID_FMT,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering command->path, pid),
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering NULL);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering /* We add the new process to the cgroup both in the child (so
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * that we can be sure that no user code is ever executed
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * outside of the cgroup) and in the parent (so that we can be
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * sure that when we kill the cgroup the process will be
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering * killed too). */
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (params->cgroup_path)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering cg_attach(SYSTEMD_CGROUP_CONTROLLER, params->cgroup_path, pid);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering exec_status_start(&command->exec_status, pid);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering *ret = pid;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return 0;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringvoid exec_context_init(ExecContext *c) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(c);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->umask = 0022;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 0);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->cpu_sched_policy = SCHED_OTHER;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->syslog_priority = LOG_DAEMON|LOG_INFO;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->syslog_level_prefix = true;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->ignore_sigpipe = true;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->timer_slack_nsec = NSEC_INFINITY;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->personality = 0xffffffffUL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->runtime_directory_mode = 0755;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringvoid exec_context_done(ExecContext *c) {
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering unsigned l;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(c);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->environment);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->environment = NULL;
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->environment_files);
7079cfeffb6d520f20ddff53fd78467e72e6cc94Lennart Poettering c->environment_files = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering for (l = 0; l < ELEMENTSOF(c->rlimit); l++) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->rlimit[l]);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->rlimit[l] = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->working_directory);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->working_directory = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->root_directory);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->root_directory = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->tty_path);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->tty_path = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->syslog_identifier);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->syslog_identifier = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->user);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->user = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->group);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->group = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->supplementary_groups);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->supplementary_groups = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(c->pam_name);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->pam_name = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (c->capabilities) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering cap_free(c->capabilities);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->capabilities = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->read_only_dirs);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->read_only_dirs = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->read_write_dirs);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->read_write_dirs = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->inaccessible_dirs);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering c->inaccessible_dirs = NULL;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (c->cpuset)
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering CPU_FREE(c->cpuset);
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering free(c->utmp_id);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering c->utmp_id = NULL;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering free(c->selinux_context);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering c->selinux_context = NULL;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering free(c->apparmor_profile);
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering c->apparmor_profile = NULL;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering set_free(c->syscall_filter);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering c->syscall_filter = NULL;
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering set_free(c->syscall_archs);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering c->syscall_archs = NULL;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering set_free(c->address_families);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering c->address_families = NULL;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering strv_free(c->runtime_directory);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering c->runtime_directory = NULL;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering bus_endpoint_free(c->bus_endpoint);
7f444afa1b62920265fec99a61cb4dc53d521956Lennart Poettering c->bus_endpoint = NULL;
7f444afa1b62920265fec99a61cb4dc53d521956Lennart Poettering}
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringint exec_context_destroy_runtime_directory(ExecContext *c, const char *runtime_prefix) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char **i;
cd61c3bfd718fb398cc53ced906266a9297782c9Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering assert(c);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (!runtime_prefix)
ebd011d95b61a86258dece9864f65b7c4af721c0Lennart Poettering return 0;
e45fc5e738b0b7700e8b4f3c4b25c58a49b44b27Lennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering STRV_FOREACH(i, c->runtime_directory) {
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering _cleanup_free_ char *p;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering p = strjoin(runtime_prefix, "/", *i, NULL);
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering if (!p)
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return -ENOMEM;
f2cbe59e113f08549949a76ac5b9b3972df4cc30Lennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering /* We execute this synchronously, since we need to be
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering * sure this is gone when we start the service
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering * next. */
56b921c3d863f0e098f60f934e6c5880575c68abZbigniew Jędrzejewski-Szmek rm_rf(p, false, true, false);
fefdc04b38725457a91651218feb7000f6ccc1f4Lennart Poettering }
086821244b5113f00a0ef993b78dc56aae2a8f6cLennart Poettering
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering return 0;
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering}
ebd93cb684806ac0f352139e69ac8f53eb49f5e4Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringvoid exec_command_done(ExecCommand *c) {
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering assert(c);
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering free(c->path);
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering c->path = NULL;
b5b38b41c37dbe1a117af9bf99e94b58ac91239aLennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering strv_free(c->argv);
f7621db0e38c3e96d48766ae648f1b7a0949ea13Lennart Poettering c->argv = NULL;
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering}
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid exec_command_done_array(ExecCommand *c, unsigned n) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < n; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering exec_command_done(c+i);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel AndersenExecCommand* exec_command_free_list(ExecCommand *c) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ExecCommand *i;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering while ((i = c)) {
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering LIST_REMOVE(command, c, i);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering exec_command_done(i);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering free(i);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid exec_command_free_array(ExecCommand **c, unsigned n) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering for (i = 0; i < n; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering c[i] = exec_command_free_list(c[i]);
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringtypedef struct InvalidEnvInfo {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering const char *unit_id;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering const char *path;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering} InvalidEnvInfo;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poetteringstatic void invalid_env(const char *p, void *userdata) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering InvalidEnvInfo *info = userdata;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering log_unit_error(info->unit_id, "Ignoring invalid environment assignment '%s': %s", p, info->path);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringint exec_context_load_environment(const ExecContext *c, const char *unit_id, char ***l) {
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering char **i, **r = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(c);
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering assert(l);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering STRV_FOREACH(i, c->environment_files) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *fn;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int k;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering bool ignore = false;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **p;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_globfree_ glob_t pglob = {};
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering int count, n;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering fn = *i;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (fn[0] == '-') {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ignore = true;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fn ++;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (!path_is_absolute(fn)) {
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering if (ignore)
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering continue;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strv_free(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Filename supports globbing, take all matching files */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering errno = 0;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (glob(fn, 0, NULL, &pglob) != 0) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (ignore)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering continue;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strv_free(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return errno ? -errno : -EINVAL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering count = pglob.gl_pathc;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (count == 0) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (ignore)
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering continue;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering strv_free(r);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return -EINVAL;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering }
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering for (n = 0; n < count; n++) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering k = load_env_file(NULL, pglob.gl_pathv[n], NULL, &p);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (k < 0) {
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering if (ignore)
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering continue;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering strv_free(r);
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering return k;
8b0cc9a36c8f92f010f2e8465942d2cd7c580d78Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering /* Log invalid environment variables with filename */
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (p) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering InvalidEnvInfo info = {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering .unit_id = unit_id,
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen .path = pglob.gl_pathv[n]
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen };
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen
e56056e93d33619a3acf13e483900b4f8938228fThomas Hindoe Paaboel Andersen p = strv_env_clean_with_callback(p, invalid_env, &info);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (r == NULL)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering r = p;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering else {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **m;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering m = strv_env_merge(2, r, p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strv_free(r);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering strv_free(p);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (!m)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering return -ENOMEM;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering r = m;
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering }
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering }
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering *l = r;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering return 0;
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poettering}
de33fc625725d199629ed074d6278504deb23debLennart Poettering
a7893c6b28772edbc7e1fea3c209caa54d465648Lennart Poetteringstatic bool tty_may_match_dev_console(const char *tty) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *active = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char *console;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (startswith(tty, "/dev/"))
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering tty += 5;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering /* trivial identity? */
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering if (streq(tty, "console"))
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering return true;
785890acf6d629ff881a1f065f431df1b7fc8c7aLennart Poettering
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering console = resolve_dev_console(&active);
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering /* if we could not resolve, assume it may */
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering if (!console)
d8f52ed25a9edce75fda5251c977b7898e33887eLennart Poettering return true;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering /* "tty0" means the active VC, so it may be the same sometimes */
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering return streq(console, tty) || (streq(console, "tty0") && tty_is_vc(tty));
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering}
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poettering
6e18cc9fa078d2a967251017ddb5baefb104b720Lennart Poetteringbool exec_context_may_touch_console(ExecContext *ec) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering return (ec->tty_reset || ec->tty_vhangup || ec->tty_vt_disallocate ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering is_terminal_input(ec->std_input) ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering is_terminal_output(ec->std_output) ||
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering is_terminal_output(ec->std_error)) &&
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering tty_may_match_dev_console(tty_path(ec));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poetteringstatic void strv_fprintf(FILE *f, char **l) {
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering char **g;
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering assert(f);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering STRV_FOREACH(g, l)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fprintf(f, " %s", *g);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering}
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poetteringvoid exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering char **e;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering unsigned i;
eb9da376d76b48585b3b63b4f91903b54f7abd36Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(c);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering assert(f);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering prefix = strempty(prefix);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering fprintf(f,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "%sUMask: %04o\n"
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "%sWorkingDirectory: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sRootDirectory: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sNonBlocking: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sPrivateTmp: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sPrivateNetwork: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sPrivateDevices: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sProtectHome: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sProtectSystem: %s\n"
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering "%sIgnoreSIGPIPE: %s\n",
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, c->umask,
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, c->working_directory ? c->working_directory : "/",
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, c->root_directory ? c->root_directory : "/",
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, yes_no(c->non_blocking),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, yes_no(c->private_tmp),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, yes_no(c->private_network),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, yes_no(c->private_devices),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, protect_home_to_string(c->protect_home),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, protect_system_to_string(c->protect_system),
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering prefix, yes_no(c->ignore_sigpipe));
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering STRV_FOREACH(e, c->environment)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fprintf(f, "%sEnvironment: %s\n", prefix, *e);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering STRV_FOREACH(e, c->environment_files)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fprintf(f, "%sEnvironmentFile: %s\n", prefix, *e);
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering if (c->nice_set)
3d7415f43f0fe6a821d7bc4a341ba371e8a30ef3Lennart Poettering fprintf(f,
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering "%sNice: %i\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering prefix, c->nice);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (c->oom_score_adjust_set)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(f,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "%sOOMScoreAdjust: %i\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering prefix, c->oom_score_adjust);
249968612f16a71df909d6e73785c18a9ff36a65Lennart Poettering
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering for (i = 0; i < RLIM_NLIMITS; i++)
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (c->rlimit[i])
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(f, "%s%s: "RLIM_FMT"\n",
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering if (c->ioprio_set) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *class_str = NULL;
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering ioprio_class_to_string_alloc(IOPRIO_PRIO_CLASS(c->ioprio), &class_str);
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering fprintf(f,
d21ed1ead18d16d35c30299a69d3366847f8a039Lennart Poettering "%sIOSchedulingClass: %s\n"
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen "%sIOPriority: %i\n",
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt prefix, strna(class_str),
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen prefix, (int) IOPRIO_PRIO_DATA(c->ioprio));
a1da85830bfaa77b9eb9c54693e5573559c97e50Tom Gundersen }
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
56159e0d918e9a9be07988133bb2847779325de0Lennart Poettering if (c->cpu_sched_set) {
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering _cleanup_free_ char *policy_str = NULL;
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering sched_policy_to_string_alloc(c->cpu_sched_policy, &policy_str);
acf97e213e69a97e63ab8f7fad7ecd53608c757aLennart Poettering fprintf(f,
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering "%sCPUSchedulingPolicy: %s\n"
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering "%sCPUSchedulingPriority: %i\n"
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering "%sCPUSchedulingResetOnFork: %s\n",
84f6181c2ac99a0514ca5e0c8fc8c8e284caf789Lennart Poettering prefix, strna(policy_str),
1ee306e1248866617c96ed9f4263f375588ad838Lennart Poettering 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 != 0xffffffffUL)
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 = strappenda(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) {
free(r->tmp_dir);
free(r->var_tmp_dir);
safe_close_pair(r->netns_storage_socket);
free(r);
}
return NULL;
}
int exec_runtime_serialize(ExecRuntime *rt, Unit *u, FILE *f, FDSet *fds) {
assert(u);
assert(f);
assert(fds);
if (!rt)
return 0;
if (rt->tmp_dir)
unit_serialize_item(u, f, "tmp-dir", rt->tmp_dir);
if (rt->var_tmp_dir)
unit_serialize_item(u, f, "var-tmp-dir", rt->var_tmp_dir);
if (rt->netns_storage_socket[0] >= 0) {
int copy;
copy = fdset_put_dup(fds, rt->netns_storage_socket[0]);
if (copy < 0)
return copy;
unit_serialize_item_format(u, f, "netns-socket-0", "%i", copy);
}
if (rt->netns_storage_socket[1] >= 0) {
int copy;
copy = fdset_put_dup(fds, rt->netns_storage_socket[1]);
if (copy < 0)
return copy;
unit_serialize_item_format(u, f, "netns-socket-1", "%i", copy);
}
return 0;
}
int exec_runtime_deserialize_item(ExecRuntime **rt, Unit *u, const char *key, const char *value, FDSet *fds) {
int r;
assert(rt);
assert(key);
assert(value);
if (streq(key, "tmp-dir")) {
char *copy;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
copy = strdup(value);
if (!copy)
return log_oom();
free((*rt)->tmp_dir);
(*rt)->tmp_dir = copy;
} else if (streq(key, "var-tmp-dir")) {
char *copy;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
copy = strdup(value);
if (!copy)
return log_oom();
free((*rt)->var_tmp_dir);
(*rt)->var_tmp_dir = copy;
} else if (streq(key, "netns-socket-0")) {
int fd;
r = exec_runtime_allocate(rt);
if (r < 0)
return r;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_unit_debug(u->id, "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 r;
if (safe_atoi(value, &fd) < 0 || !fdset_contains(fds, fd))
log_unit_debug(u->id, "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;
rm_rf_dangerous(path, false, true, false);
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);