Skip to content

Commit

Permalink
logging: new mode -l passthrough
Browse files Browse the repository at this point in the history
when passthrough is specified, the std stream files are passed
directly to the container without conmon intercepting them.

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed Sep 23, 2021
1 parent 338e8d7 commit 7e126e8
Show file tree
Hide file tree
Showing 7 changed files with 69 additions and 30 deletions.
2 changes: 2 additions & 0 deletions runner/conmon/conmon.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type ConmonInstance struct {
pidFile string
stdout io.Writer
stderr io.Writer
stdin io.Reader

parentStartPipe *os.File
parentAttachPipe *os.File
Expand Down Expand Up @@ -61,6 +62,7 @@ func NewConmonInstance(options ...ConmonOption) (*ConmonInstance, error) {

ci.cmd.Stdout = ci.stdout
ci.cmd.Stderr = ci.stderr
ci.cmd.Stdin = ci.stdin
return ci, nil
}

Expand Down
7 changes: 7 additions & 0 deletions runner/conmon/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ func WithStderr(stderr io.Writer) ConmonOption {
}
}

func WithStdin(stdin io.Reader) ConmonOption {
return func(ci *ConmonInstance) error {
ci.stdin = stdin
return nil
}
}

func WithPath(path string) ConmonOption {
return func(ci *ConmonInstance) error {
ci.path = path
Expand Down
5 changes: 5 additions & 0 deletions runner/conmon_test/ctr_logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ var _ = Describe("conmon ctr logs", func() {
_, err := os.Stat(tmpLogPath)
Expect(err).To(BeNil())
})
It("log driver as passthrough should pass", func() {
stdout, stderr := getConmonOutputGivenLogOpts(conmon.WithLogDriver("passthrough", ""))
Expect(stdout).To(BeEmpty())
Expect(stderr).To(BeEmpty())
})
It("log driver as k8s-file with invalid path should fail", func() {
_, stderr := getConmonOutputGivenLogOpts(conmon.WithLogDriver("k8s-file", invalidPath))
Expect(stderr).To(ContainSubstring("Failed to open log file"))
Expand Down
3 changes: 2 additions & 1 deletion runner/conmon_test/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ func TestConmon(t *testing.T) {
func getConmonOutputGivenOptions(options ...conmon.ConmonOption) (string, string) {
var stdout bytes.Buffer
var stderr bytes.Buffer
var stdin bytes.Buffer

options = append(options, conmon.WithStdout(&stdout), conmon.WithStderr(&stderr))
options = append(options, conmon.WithStdout(&stdout), conmon.WithStderr(&stderr), conmon.WithStdin(&stdin))

ci, err := conmon.CreateAndExecConmon(options...)
Expect(err).To(BeNil())
Expand Down
67 changes: 38 additions & 29 deletions src/conmon.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@
#include <sys/stat.h>
#include <locale.h>

static void disconnect_std_streams(int dev_null_r, int dev_null_w)
{
if (dup2(dev_null_r, STDIN_FILENO) < 0)
pexit("Failed to dup over stdin");
if (dup2(dev_null_w, STDOUT_FILENO) < 0)
pexit("Failed to dup over stdout");
if (dup2(dev_null_w, STDERR_FILENO) < 0)
pexit("Failed to dup over stderr");
}

int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
Expand Down Expand Up @@ -114,13 +124,8 @@ int main(int argc, char *argv[])
/* Disconnect stdio from parent. We need to do this, because
the parent is waiting for the stdout to end when the intermediate
child dies */
if (dup2(dev_null_r, STDIN_FILENO) < 0)
pexit("Failed to dup over stdin");
if (dup2(dev_null_w, STDOUT_FILENO) < 0)
pexit("Failed to dup over stdout");
if (dup2(dev_null_w, STDERR_FILENO) < 0)
pexit("Failed to dup over stderr");

if (!logging_is_passthrough())
disconnect_std_streams(dev_null_r, dev_null_w);
/* Create a new session group */
setsid();

Expand Down Expand Up @@ -193,7 +198,7 @@ int main(int argc, char *argv[])

/* Setup endpoint for attach */
_cleanup_free_ char *attach_symlink_dir_path = NULL;
if (opt_bundle_path != NULL) {
if (opt_bundle_path != NULL && !logging_is_passthrough()) {
attach_symlink_dir_path = setup_attach_socket();
dummyfd = setup_terminal_control_fifo();
setup_console_fifo();
Expand Down Expand Up @@ -227,27 +232,28 @@ int main(int argc, char *argv[])
if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
_pexit("Failed to unblock signals");

if (workerfd_stdin < 0)
workerfd_stdin = dev_null_r;
if (dup2(workerfd_stdin, STDIN_FILENO) < 0)
_pexit("Failed to dup over stdin");
if (workerfd_stdin != dev_null_r && fchmod(STDIN_FILENO, 0777) < 0)
nwarn("Failed to chown stdin");

if (workerfd_stdout < 0)
workerfd_stdout = dev_null_w;
if (dup2(workerfd_stdout, STDOUT_FILENO) < 0)
_pexit("Failed to dup over stdout");
if (workerfd_stdout != dev_null_w && fchmod(STDOUT_FILENO, 0777) < 0)
nwarn("Failed to chown stdout");

if (workerfd_stderr < 0)
workerfd_stderr = workerfd_stdout;
if (dup2(workerfd_stderr, STDERR_FILENO) < 0)
_pexit("Failed to dup over stderr");
if (workerfd_stderr != dev_null_w && fchmod(STDERR_FILENO, 0777) < 0)
nwarn("Failed to chown stderr");

if (!logging_is_passthrough()) {
if (workerfd_stdin < 0)
workerfd_stdin = dev_null_r;
if (dup2(workerfd_stdin, STDIN_FILENO) < 0)
_pexit("Failed to dup over stdin");
if (workerfd_stdin != dev_null_r && fchmod(STDIN_FILENO, 0777) < 0)
nwarn("Failed to chown stdin");

if (workerfd_stdout < 0)
workerfd_stdout = dev_null_w;
if (dup2(workerfd_stdout, STDOUT_FILENO) < 0)
_pexit("Failed to dup over stdout");
if (workerfd_stdout != dev_null_w && fchmod(STDOUT_FILENO, 0777) < 0)
nwarn("Failed to chown stdout");

if (workerfd_stderr < 0)
workerfd_stderr = workerfd_stdout;
if (dup2(workerfd_stderr, STDERR_FILENO) < 0)
_pexit("Failed to dup over stderr");
if (workerfd_stderr != dev_null_w && fchmod(STDERR_FILENO, 0777) < 0)
nwarn("Failed to chown stderr");
}
/* If LISTEN_PID env is set, we need to set the LISTEN_PID
it to the new child process */
char *listenpid = getenv("LISTEN_PID");
Expand Down Expand Up @@ -287,6 +293,9 @@ int main(int argc, char *argv[])
exit(127);
}

if (logging_is_passthrough())
disconnect_std_streams(dev_null_r, dev_null_w);

if ((signal(SIGTERM, on_sig_exit) == SIG_ERR) || (signal(SIGQUIT, on_sig_exit) == SIG_ERR)
|| (signal(SIGINT, on_sig_exit) == SIG_ERR))
pexit("Failed to register the signal handler");
Expand Down
14 changes: 14 additions & 0 deletions src/ctr_logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ static inline int sd_journal_sendv(G_GNUC_UNUSED const struct iovec *iov, G_GNUC
/* Different types of container logging */
static gboolean use_journald_logging = FALSE;
static gboolean use_k8s_logging = FALSE;
static gboolean use_logging_passthrough = FALSE;

/* Value the user must input for each log driver */
static const char *const K8S_FILE_STRING = "k8s-file";
Expand Down Expand Up @@ -71,6 +72,11 @@ static int set_k8s_timestamp(char *buf, ssize_t buflen, const char *pipename);
static void reopen_k8s_file(void);


gboolean logging_is_passthrough(void)
{
return use_logging_passthrough;
}

/*
* configures container log specific information, such as the drivers the user
* called with and the max log size for log file types. For the log file types
Expand Down Expand Up @@ -160,6 +166,14 @@ static void parse_log_path(char *log_config)
return;
}

if (!strcmp(driver, "passthrough")) {
if (isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO))
nexitf("cannot use a tty with passthrough logging mode to prevent attacks via TIOCSTI");

use_logging_passthrough = TRUE;
return;
}

if (!strcmp(driver, JOURNALD_FILE_STRING)) {
use_journald_logging = TRUE;
return;
Expand Down
1 change: 1 addition & 0 deletions src/ctr_logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ void reopen_log_files(void);
bool write_to_logs(stdpipe_t pipe, char *buf, ssize_t num_read);
void configure_log_drivers(gchar **log_drivers, int64_t log_size_max_, char *cuuid_, char *name_, char *tag);
void sync_logs(void);
gboolean logging_is_passthrough(void);

#endif /* !defined(CTR_LOGGING_H) */

0 comments on commit 7e126e8

Please sign in to comment.