#include "securebits.h"
#include "cgroup.h"
#include "namespace.h"
+#include "tcpwrap.h"
/* This assumes there is a 'tty' group */
#define TTY_MODE 0620
"%i\n"
"%s\n"
"%i\n",
- output == EXEC_OUTPUT_KERNEL ? "kmsg" : "syslog",
+ output == EXEC_OUTPUT_KMSG ? "kmsg" : "syslog",
context->syslog_priority,
context->syslog_identifier ? context->syslog_identifier : ident,
!context->syslog_no_prefix);
i == EXEC_INPUT_TTY_FAIL;
}
-static int fixup_input(const ExecContext *context, int socket_fd) {
- assert(context);
+static int fixup_input(ExecInput std_input, int socket_fd) {
- if (socket_fd < 0 && context->std_input == EXEC_INPUT_SOCKET)
+ if (std_input == EXEC_INPUT_SOCKET && socket_fd < 0)
return EXEC_INPUT_NULL;
- return context->std_input;
+ return std_input;
}
-static int fixup_output(const ExecContext *context, int socket_fd) {
- assert(context);
+static int fixup_output(ExecOutput std_output, int socket_fd) {
- if (socket_fd < 0 && context->std_output == EXEC_OUTPUT_SOCKET)
+ if (std_output == EXEC_OUTPUT_SOCKET && socket_fd < 0)
return EXEC_OUTPUT_INHERIT;
- return context->std_output;
-}
-
-static int fixup_error(const ExecContext *context, int socket_fd) {
- assert(context);
-
- if (socket_fd < 0 && context->std_error == EXEC_OUTPUT_SOCKET)
- return EXEC_OUTPUT_INHERIT;
-
- return context->std_error;
+ return std_output;
}
static int setup_input(const ExecContext *context, int socket_fd) {
assert(context);
- i = fixup_input(context, socket_fd);
+ i = fixup_input(context->std_input, socket_fd);
switch (i) {
if ((fd = acquire_terminal(
tty_path(context),
i == EXEC_INPUT_TTY_FAIL,
- i == EXEC_INPUT_TTY_FORCE)) < 0)
+ i == EXEC_INPUT_TTY_FORCE,
+ false)) < 0)
return fd;
if (fd != STDIN_FILENO) {
assert(context);
assert(ident);
- i = fixup_input(context, socket_fd);
- o = fixup_output(context, socket_fd);
+ i = fixup_input(context->std_input, socket_fd);
+ o = fixup_output(context->std_output, socket_fd);
/* This expects the input is already set up */
case EXEC_OUTPUT_INHERIT:
/* If the input is connected to a terminal, inherit that... */
- if (is_terminal_input(i) || i == EXEC_INPUT_SOCKET)
+ if (i != EXEC_INPUT_NULL)
return dup2(STDIN_FILENO, STDOUT_FILENO) < 0 ? -errno : STDOUT_FILENO;
- return STDIN_FILENO;
+ /* For PID 1 stdout is always connected to /dev/null,
+ * hence reopen the console if out parent is PID1. */
+ if (getppid() == 1)
+ return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
+
+ return STDOUT_FILENO;
case EXEC_OUTPUT_NULL:
return open_null_as(O_WRONLY, STDOUT_FILENO);
return open_terminal_as(tty_path(context), O_WRONLY, STDOUT_FILENO);
case EXEC_OUTPUT_SYSLOG:
- case EXEC_OUTPUT_KERNEL:
+ case EXEC_OUTPUT_KMSG:
return connect_logger_as(context, o, ident, STDOUT_FILENO);
case EXEC_OUTPUT_SOCKET:
assert(context);
assert(ident);
- i = fixup_input(context, socket_fd);
- o = fixup_output(context, socket_fd);
- e = fixup_error(context, socket_fd);
+ i = fixup_input(context->std_input, socket_fd);
+ o = fixup_output(context->std_output, socket_fd);
+ e = fixup_output(context->std_error, socket_fd);
/* This expects the input and output are already set up */
* the way and are not on a tty */
if (e == EXEC_OUTPUT_INHERIT &&
o == EXEC_OUTPUT_INHERIT &&
- !is_terminal_input(i))
+ i != EXEC_INPUT_NULL &&
+ getppid () != 1)
return STDERR_FILENO;
/* Duplicate form stdout if possible */
return open_terminal_as(tty_path(context), O_WRONLY, STDERR_FILENO);
case EXEC_OUTPUT_SYSLOG:
- case EXEC_OUTPUT_KERNEL:
+ case EXEC_OUTPUT_KMSG:
return connect_logger_as(context, e, ident, STDERR_FILENO);
case EXEC_OUTPUT_SOCKET:
if ((fd = acquire_terminal(
tty_path(context),
context->std_input == EXEC_INPUT_TTY_FAIL,
- context->std_input == EXEC_INPUT_TTY_FORCE)) < 0) {
+ context->std_input == EXEC_INPUT_TTY_FORCE,
+ false)) < 0) {
r = EXIT_STDIN;
goto fail;
}
/* child */
- reset_all_signal_handlers();
+ /* We reset exactly these signals, since they are the
+ * only ones we set to SIG_IGN in the main daemon. All
+ * others we leave untouched because we set them to
+ * SIG_DFL or a valid handler initially, both of which
+ * will be demoted to SIG_DFL. */
+ default_signals(SIGNALS_CRASH_HANDLER,
+ SIGNALS_IGNORE, -1);
if (sigemptyset(&ss) < 0 ||
sigprocmask(SIG_SETMASK, &ss, NULL) < 0) {
goto fail;
}
+ if (socket_fd >= 0 && context->tcpwrap_name)
+ if (!socket_tcpwrap(socket_fd, context->tcpwrap_name)) {
+ r = EXIT_TCPWRAP;
+ goto fail;
+ }
+
if (confirm_spawn) {
char response;
goto fail;
}
- if (strv_length(context->read_write_dirs) > 0 ||
- strv_length(context->read_only_dirs) > 0 ||
- strv_length(context->inaccessible_dirs) > 0 ||
- context->mount_flags != MS_SHARED ||
- context->private_tmp)
- if ((r = setup_namespace(
- context->read_write_dirs,
- context->read_only_dirs,
- context->inaccessible_dirs,
- context->private_tmp,
- context->mount_flags)) < 0)
- goto fail;
-
if (context->user) {
username = context->user;
if (get_user_creds(&username, &uid, &gid, &home) < 0) {
umask(context->umask);
+ if (strv_length(context->read_write_dirs) > 0 ||
+ strv_length(context->read_only_dirs) > 0 ||
+ strv_length(context->inaccessible_dirs) > 0 ||
+ context->mount_flags != MS_SHARED ||
+ context->private_tmp)
+ if ((r = setup_namespace(
+ context->read_write_dirs,
+ context->read_only_dirs,
+ context->inaccessible_dirs,
+ context->private_tmp,
+ context->mount_flags)) < 0)
+ goto fail;
+
if (apply_chroot) {
if (context->root_directory)
if (chroot(context->root_directory) < 0) {
free(c->tty_path);
c->tty_path = NULL;
+ free(c->tcpwrap_name);
+ c->tcpwrap_name = NULL;
+
free(c->syslog_identifier);
c->syslog_identifier = NULL;
for (e = c->environment; *e; e++)
fprintf(f, "%sEnvironment: %s\n", prefix, *e);
+ if (c->tcpwrap_name)
+ fprintf(f,
+ "%sTCPWrapName: %s\n",
+ prefix, c->tcpwrap_name);
+
if (c->nice_set)
fprintf(f,
"%sNice: %i\n",
"%sTTYPath: %s\n",
prefix, c->tty_path);
- if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KERNEL ||
- c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KERNEL)
+ if (c->std_output == EXEC_OUTPUT_SYSLOG || c->std_output == EXEC_OUTPUT_KMSG ||
+ c->std_error == EXEC_OUTPUT_SYSLOG || c->std_error == EXEC_OUTPUT_KMSG)
fprintf(f,
"%sSyslogFacility: %s\n"
"%sSyslogLevel: %s\n",
case EXIT_STDERR:
return "STDERR";
+ case EXIT_TCPWRAP:
+ return "TCPWRAP";
+
default:
return NULL;
}
[EXEC_OUTPUT_NULL] = "null",
[EXEC_OUTPUT_TTY] = "tty",
[EXEC_OUTPUT_SYSLOG] = "syslog",
- [EXEC_OUTPUT_KERNEL] = "kernel",
+ [EXEC_OUTPUT_KMSG] = "kmsg",
[EXEC_OUTPUT_SOCKET] = "socket"
};