diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index a8e9fc0102..7fc4a80091 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -980,12 +980,12 @@ func AutocompleteImageVolume(cmd *cobra.Command, args []string, toComplete strin } // AutocompleteLogDriver - Autocomplete log-driver options. -// -> "journald", "none", "k8s-file", "passthrough" +// -> "journald", "none", "k8s-file", "passthrough", "passthrough-tty" func AutocompleteLogDriver(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { // don't show json-file logDrivers := []string{define.JournaldLogging, define.NoLogging, define.KubernetesLogging} if !registry.IsRemote() { - logDrivers = append(logDrivers, define.PassthroughLogging) + logDrivers = append(logDrivers, define.PassthroughLogging, define.PassthroughTTYLogging) } return logDrivers, cobra.ShellCompDirectiveNoFileComp } diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 49f2e98399..6e33594379 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -189,7 +189,7 @@ func create(cmd *cobra.Command, args []string) error { } } - if cliVals.LogDriver != define.PassthroughLogging { + if cliVals.LogDriver != define.PassthroughLogging && cliVals.LogDriver != define.PassthroughTTYLogging { fmt.Println(report.Id) } return nil @@ -239,12 +239,17 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra if cliVals.LogDriver == define.PassthroughLogging { if term.IsTerminal(0) || term.IsTerminal(1) || term.IsTerminal(2) { - return vals, errors.New("the '--log-driver passthrough' option cannot be used on a TTY") + return vals, errors.New("the '--log-driver passthrough' option cannot be used on a TTY. If you really want it, use '--log-driver passthrough-tty'") } if registry.IsRemote() { return vals, errors.New("the '--log-driver passthrough' option is not supported in remote mode") } } + if cliVals.LogDriver == define.PassthroughTTYLogging { + if registry.IsRemote() { + return vals, errors.New("the '--log-driver passthrough-tty' option is not supported in remote mode") + } + } if !isInfra { if c.Flag("cpu-period").Changed && c.Flag("cpus").Changed { diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index 047dabb9c8..a0560e41a1 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -173,7 +173,7 @@ func run(cmd *cobra.Command, args []string) error { runOpts.InputStream = nil } - passthrough := cliVals.LogDriver == define.PassthroughLogging + passthrough := cliVals.LogDriver == define.PassthroughLogging || cliVals.LogDriver == define.PassthroughTTYLogging // If attach is set, clear stdin/stdout/stderr and only attach requested if cmd.Flag("attach").Changed { diff --git a/docs/source/markdown/options/log-driver.md b/docs/source/markdown/options/log-driver.md index 754a97c022..d99f229c5e 100644 --- a/docs/source/markdown/options/log-driver.md +++ b/docs/source/markdown/options/log-driver.md @@ -4,7 +4,7 @@ ####> are applicable to all of those. #### **--log-driver**=*driver* -Logging driver for the container. Currently available options are **k8s-file**, **journald**, **none** and **passthrough**, with **json-file** aliased to **k8s-file** for scripting compatibility. (Default **journald**). +Logging driver for the container. Currently available options are **k8s-file**, **journald**, **none**, **passthrough** and **passthrough-tty**, with **json-file** aliased to **k8s-file** for scripting compatibility. (Default **journald**). The podman info command below displays the default log-driver for the system. ``` @@ -14,3 +14,5 @@ journald The **passthrough** driver passes down the standard streams (stdin, stdout, stderr) to the container. It is not allowed with the remote Podman client, including Mac and Windows (excluding WSL2) machines, and on a tty, since it is vulnerable to attacks via TIOCSTI. + +The **passthrough-tty** driver is the same as **passthrough** except that it also allows it to be used on a TTY if the user really wants it. diff --git a/libpod/container_api.go b/libpod/container_api.go index 8b1d677d34..b48cf84826 100644 --- a/libpod/container_api.go +++ b/libpod/container_api.go @@ -172,7 +172,7 @@ func (c *Container) StartAndAttach(ctx context.Context, streams *define.AttachSt // Attach to the container before starting it go func() { // Start resizing - if c.LogDriver() != define.PassthroughLogging { + if c.LogDriver() != define.PassthroughLogging && c.LogDriver() != define.PassthroughTTYLogging { registerResizeFunc(resize, c.bundlePath()) } @@ -304,6 +304,9 @@ func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <- if c.LogDriver() == define.PassthroughLogging { return fmt.Errorf("this container is using the 'passthrough' log driver, cannot attach: %w", define.ErrNoLogs) } + if c.LogDriver() == define.PassthroughTTYLogging { + return fmt.Errorf("this container is using the 'passthrough-tty' log driver, cannot attach: %w", define.ErrNoLogs) + } if !c.batched { c.lock.Lock() if err := c.syncContainer(); err != nil { @@ -336,7 +339,7 @@ func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <- } // Start resizing - if c.LogDriver() != define.PassthroughLogging { + if c.LogDriver() != define.PassthroughLogging && c.LogDriver() != define.PassthroughTTYLogging { registerResizeFunc(resize, c.bundlePath()) } diff --git a/libpod/define/config.go b/libpod/define/config.go index e5729d47ea..cf9fd3812e 100644 --- a/libpod/define/config.go +++ b/libpod/define/config.go @@ -82,6 +82,9 @@ const NoLogging = "none" // PassthroughLogging is the string conmon expects when specifying to use the passthrough driver const PassthroughLogging = "passthrough" +// PassthroughTTYLogging is the string conmon expects when specifying to use the passthrough driver even on a tty. +const PassthroughTTYLogging = "passthrough-tty" + // DefaultRlimitValue is the value set by default for nofile and nproc const RLimitDefaultValue = uint64(1048576) diff --git a/libpod/oci_conmon_attach_common.go b/libpod/oci_conmon_attach_common.go index a1d102fc18..64fc0f41be 100644 --- a/libpod/oci_conmon_attach_common.go +++ b/libpod/oci_conmon_attach_common.go @@ -33,7 +33,7 @@ const ( // Does not check if state is appropriate. // started is only required if startContainer is true. func (r *ConmonOCIRuntime) Attach(c *Container, params *AttachOptions) error { - passthrough := c.LogDriver() == define.PassthroughLogging + passthrough := c.LogDriver() == define.PassthroughLogging || c.LogDriver() == define.PassthroughTTYLogging if params == nil || params.Streams == nil { return fmt.Errorf("must provide parameters to Attach: %w", define.ErrInternal) diff --git a/libpod/oci_conmon_common.go b/libpod/oci_conmon_common.go index 73179378f6..c544f0f75a 100644 --- a/libpod/oci_conmon_common.go +++ b/libpod/oci_conmon_common.go @@ -1417,7 +1417,7 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p logDriverArg = define.JournaldLogging case define.NoLogging: logDriverArg = define.NoLogging - case define.PassthroughLogging: + case define.PassthroughLogging, define.PassthroughTTYLogging: logDriverArg = define.PassthroughLogging //lint:ignore ST1015 the default case has to be here default: //nolint:gocritic diff --git a/libpod/options.go b/libpod/options.go index e8dd7b931c..5a6b599300 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -1101,7 +1101,7 @@ func WithLogDriver(driver string) CtrCreateOption { switch driver { case "": return fmt.Errorf("log driver must be set: %w", define.ErrInvalidArg) - case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging: + case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging, define.PassthroughTTYLogging: break default: return fmt.Errorf("invalid log driver: %w", define.ErrInvalidArg) diff --git a/test/system/450-interactive.bats b/test/system/450-interactive.bats index 1eaa17ac2b..18ff460866 100644 --- a/test/system/450-interactive.bats +++ b/test/system/450-interactive.bats @@ -102,4 +102,24 @@ function teardown() { is "$output" "hello$CR" "-i=false: no warning" } + +@test "podman run -l passthrough-tty" { + skip_if_remote + + # Requires conmon 2.1.10 or greater + want=2.1.10 + run_podman info --format '{{.Host.Conmon.Path}}' + conmon_path="$output" + conmon_version=$($conmon_path --version | sed -ne 's/^.* version //p') + if ! printf "%s\n%s\n" "$want" "$conmon_version" | sort --check=quiet --version-sort; then + skip "need conmon >= $want; have $conmon_version" + fi + + run tty <$PODMAN_TEST_PTY + expected_tty="$output" + + run_podman run -v/dev:/dev --log-driver=passthrough-tty $IMAGE tty <$PODMAN_TEST_PTY + is "$output" "$expected_tty" "passthrough-tty: tty matches" +} + # vim: filetype=sh