summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/podman/common/completion.go5
-rw-r--r--cmd/podman/containers/create.go13
-rw-r--r--cmd/podman/containers/run.go8
-rw-r--r--docs/source/markdown/podman-create.1.md6
-rw-r--r--docs/source/markdown/podman-run.1.md7
-rw-r--r--go.mod1
-rw-r--r--libpod/container_api.go4
-rw-r--r--libpod/container_log.go4
-rw-r--r--libpod/define/config.go3
-rw-r--r--libpod/oci_attach_linux.go39
-rw-r--r--libpod/oci_conmon_linux.go2
-rw-r--r--libpod/options.go2
-rw-r--r--libpod/runtime_ctr.go2
13 files changed, 73 insertions, 23 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go
index 90522438d..ea453a331 100644
--- a/cmd/podman/common/completion.go
+++ b/cmd/podman/common/completion.go
@@ -771,10 +771,13 @@ func AutocompleteImageVolume(cmd *cobra.Command, args []string, toComplete strin
}
// AutocompleteLogDriver - Autocomplete log-driver options.
-// -> "journald", "none", "k8s-file"
+// -> "journald", "none", "k8s-file", "passthrough"
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)
+ }
return logDrivers, cobra.ShellCompDirectiveNoFileComp
}
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index 8b27de53e..2593b4c44 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -19,6 +19,7 @@ import (
"github.com/containers/podman/v3/pkg/specgen"
"github.com/containers/podman/v3/pkg/specgenutil"
"github.com/containers/podman/v3/pkg/util"
+ "github.com/mattn/go-isatty"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -161,7 +162,9 @@ func create(cmd *cobra.Command, args []string) error {
}
}
- fmt.Println(report.Id)
+ if cliVals.LogDriver != define.PassthroughLogging {
+ fmt.Println(report.Id)
+ }
return nil
}
@@ -188,6 +191,14 @@ func CreateInit(c *cobra.Command, vals entities.ContainerCreateOptions, isInfra
vals.UserNS = "private"
}
}
+ if cliVals.LogDriver == define.PassthroughLogging {
+ if isatty.IsTerminal(0) || isatty.IsTerminal(1) || isatty.IsTerminal(2) {
+ return vals, errors.New("the '--log-driver passthrough' option cannot be used on a TTY")
+ }
+ if registry.IsRemote() {
+ return vals, errors.New("the '--log-driver passthrough' option is not supported in remote mode")
+ }
+ }
if !isInfra {
if c.Flag("shm-size").Changed {
diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go
index d14961829..071708b76 100644
--- a/cmd/podman/containers/run.go
+++ b/cmd/podman/containers/run.go
@@ -158,8 +158,13 @@ func run(cmd *cobra.Command, args []string) error {
runOpts.InputStream = nil
}
+ passthrough := cliVals.LogDriver == define.PassthroughLogging
+
// If attach is set, clear stdin/stdout/stderr and only attach requested
if cmd.Flag("attach").Changed {
+ if passthrough {
+ return errors.Wrapf(define.ErrInvalidArg, "cannot specify --attach with --log-driver=passthrough")
+ }
runOpts.OutputStream = nil
runOpts.ErrorStream = nil
if !cliVals.Interactive {
@@ -179,6 +184,7 @@ func run(cmd *cobra.Command, args []string) error {
}
}
}
+
cliVals.PreserveFDs = runOpts.PreserveFDs
s := specgen.NewSpecGenerator(imageName, cliVals.RootFS)
if err := specgenutil.FillOutSpecGen(s, &cliVals, args); err != nil {
@@ -200,7 +206,7 @@ func run(cmd *cobra.Command, args []string) error {
return err
}
- if runOpts.Detach {
+ if runOpts.Detach && !passthrough {
fmt.Println(report.Id)
return nil
}
diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md
index f63f5ca9c..0630c8be9 100644
--- a/docs/source/markdown/podman-create.1.md
+++ b/docs/source/markdown/podman-create.1.md
@@ -513,7 +513,11 @@ Not implemented
#### **--log-driver**="*k8s-file*"
-Logging driver for the container. Currently available options are *k8s-file*, *journald*, and *none*, with *json-file* aliased to *k8s-file* for scripting compatibility.
+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.
+
+The *passthrough* driver passes down the standard streams (stdin, stdout, stderr) to the
+container. It is not allowed with the remote Podman client and on a tty, since it is
+vulnerable to attacks via TIOCSTI.
#### **--log-opt**=*name*=*value*
diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md
index 6d68fd62b..43b6d5cc6 100644
--- a/docs/source/markdown/podman-run.1.md
+++ b/docs/source/markdown/podman-run.1.md
@@ -538,7 +538,12 @@ Not implemented.
#### **--log-driver**="*driver*"
-Logging driver for the container. Currently available options are **k8s-file**, **journald**, and **none**, with **json-file** aliased to **k8s-file** for scripting compatibility.
+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.
+
+The **passthrough** driver passes down the standard streams (stdin, stdout, stderr) to the
+container. It is not allowed with the remote Podman client and on a tty, since it is
+vulnerable to attacks via TIOCSTI.
+
#### **--log-opt**=*name*=*value*
diff --git a/go.mod b/go.mod
index 3b6e38392..973b149a3 100644
--- a/go.mod
+++ b/go.mod
@@ -41,6 +41,7 @@ require (
github.com/hpcloud/tail v1.0.0
github.com/json-iterator/go v1.1.12
github.com/mattn/go-colorable v0.1.8 // indirect
+ github.com/mattn/go-isatty v0.0.12
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/mrunalp/fileutils v0.5.0
github.com/onsi/ginkgo v1.16.4
diff --git a/libpod/container_api.go b/libpod/container_api.go
index 2d5b07a35..50be0eea4 100644
--- a/libpod/container_api.go
+++ b/libpod/container_api.go
@@ -229,6 +229,10 @@ func (c *Container) Kill(signal uint) error {
// This function returns when the attach finishes. It does not hold the lock for
// the duration of its runtime, only using it at the beginning to verify state.
func (c *Container) Attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize) error {
+ switch c.LogDriver() {
+ case define.PassthroughLogging:
+ return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot attach")
+ }
if !c.batched {
c.lock.Lock()
if err := c.syncContainer(); err != nil {
diff --git a/libpod/container_log.go b/libpod/container_log.go
index a65b2a44f..18840bff2 100644
--- a/libpod/container_log.go
+++ b/libpod/container_log.go
@@ -18,7 +18,7 @@ import (
var logDrivers []string
func init() {
- logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging)
+ logDrivers = append(logDrivers, define.KubernetesLogging, define.NoLogging, define.PassthroughLogging)
}
// Log is a runtime function that can read one or more container logs.
@@ -34,6 +34,8 @@ func (r *Runtime) Log(ctx context.Context, containers []*Container, options *log
// ReadLog reads a containers log based on the input options and returns log lines over a channel.
func (c *Container) ReadLog(ctx context.Context, options *logs.LogOptions, logChannel chan *logs.LogLine) error {
switch c.LogDriver() {
+ case define.PassthroughLogging:
+ return errors.Wrapf(define.ErrNoLogs, "this container is using the 'passthrough' log driver, cannot read logs")
case define.NoLogging:
return errors.Wrapf(define.ErrNoLogs, "this container is using the 'none' log driver, cannot read logs")
case define.JournaldLogging:
diff --git a/libpod/define/config.go b/libpod/define/config.go
index 6c426f2ec..7a0d39e42 100644
--- a/libpod/define/config.go
+++ b/libpod/define/config.go
@@ -78,6 +78,9 @@ const JSONLogging = "json-file"
// NoLogging is the string conmon expects when specifying to use no log driver whatsoever
const NoLogging = "none"
+// PassthroughLogging is the string conmon expects when specifying to use the passthrough driver
+const PassthroughLogging = "passthrough"
+
// Strings used for --sdnotify option to podman
const (
SdNotifyModeContainer = "container"
diff --git a/libpod/oci_attach_linux.go b/libpod/oci_attach_linux.go
index 9ae46eeda..d4d4a1076 100644
--- a/libpod/oci_attach_linux.go
+++ b/libpod/oci_attach_linux.go
@@ -40,7 +40,9 @@ func openUnixSocket(path string) (*net.UnixConn, error) {
// Does not check if state is appropriate
// started is only required if startContainer is true
func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-chan define.TerminalSize, startContainer bool, started chan bool, attachRdy chan<- bool) error {
- if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput {
+ passthrough := c.LogDriver() == define.PassthroughLogging
+
+ if !streams.AttachOutput && !streams.AttachError && !streams.AttachInput && !passthrough {
return errors.Wrapf(define.ErrInvalidArg, "must provide at least one stream to attach to")
}
if startContainer && started == nil {
@@ -52,24 +54,27 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
return err
}
- logrus.Debugf("Attaching to container %s", c.ID())
+ var conn *net.UnixConn
+ if !passthrough {
+ logrus.Debugf("Attaching to container %s", c.ID())
- registerResizeFunc(resize, c.bundlePath())
+ registerResizeFunc(resize, c.bundlePath())
- attachSock, err := c.AttachSocketPath()
- if err != nil {
- return err
- }
+ attachSock, err := c.AttachSocketPath()
+ if err != nil {
+ return err
+ }
- conn, err := openUnixSocket(attachSock)
- if err != nil {
- return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
- }
- defer func() {
- if err := conn.Close(); err != nil {
- logrus.Errorf("Unable to close socket: %q", err)
+ conn, err = openUnixSocket(attachSock)
+ if err != nil {
+ return errors.Wrapf(err, "failed to connect to container's attach socket: %v", attachSock)
}
- }()
+ defer func() {
+ if err := conn.Close(); err != nil {
+ logrus.Errorf("unable to close socket: %q", err)
+ }
+ }()
+ }
// If starting was requested, start the container and notify when that's
// done.
@@ -80,6 +85,10 @@ func (c *Container) attach(streams *define.AttachStreams, keys string, resize <-
started <- true
}
+ if passthrough {
+ return nil
+ }
+
receiveStdoutError, stdinDone := setupStdioChannels(streams, conn, detachKeys)
if attachRdy != nil {
attachRdy <- true
diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go
index f82fc4ce6..71a7b29fa 100644
--- a/libpod/oci_conmon_linux.go
+++ b/libpod/oci_conmon_linux.go
@@ -1288,6 +1288,8 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p
logDriverArg = define.JournaldLogging
case define.NoLogging:
logDriverArg = define.NoLogging
+ case define.PassthroughLogging:
+ logDriverArg = define.PassthroughLogging
case define.JSONLogging:
fallthrough
//lint:ignore ST1015 the default case has to be here
diff --git a/libpod/options.go b/libpod/options.go
index a80f51c6a..553af43fd 100644
--- a/libpod/options.go
+++ b/libpod/options.go
@@ -1114,7 +1114,7 @@ func WithLogDriver(driver string) CtrCreateOption {
switch driver {
case "":
return errors.Wrapf(define.ErrInvalidArg, "log driver must be set")
- case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging:
+ case define.JournaldLogging, define.KubernetesLogging, define.JSONLogging, define.NoLogging, define.PassthroughLogging:
break
default:
return errors.Wrapf(define.ErrInvalidArg, "invalid log driver")
diff --git a/libpod/runtime_ctr.go b/libpod/runtime_ctr.go
index 7cda9aa8b..00979a500 100644
--- a/libpod/runtime_ctr.go
+++ b/libpod/runtime_ctr.go
@@ -478,7 +478,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
}
switch ctr.config.LogDriver {
- case define.NoLogging:
+ case define.NoLogging, define.PassthroughLogging:
break
case define.JournaldLogging:
ctr.initializeJournal(ctx)