diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/domain/entities/events.go | 5 | ||||
-rw-r--r-- | pkg/domain/infra/abi/terminal/sigproxy_commn.go | 16 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/containers.go | 7 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/runtime.go | 31 | ||||
-rw-r--r-- | pkg/signal/signal_common.go | 15 | ||||
-rw-r--r-- | pkg/signal/signal_common_test.go | 49 | ||||
-rw-r--r-- | pkg/signal/signal_linux.go | 8 | ||||
-rw-r--r-- | pkg/signal/signal_linux_mipsx.go | 8 | ||||
-rw-r--r-- | pkg/signal/signal_unix.go | 8 | ||||
-rw-r--r-- | pkg/signal/signal_unsupported.go | 6 | ||||
-rw-r--r-- | pkg/util/utils_freebsd.go | 2 | ||||
-rw-r--r-- | pkg/util/utils_linux.go | 5 |
12 files changed, 145 insertions, 15 deletions
diff --git a/pkg/domain/entities/events.go b/pkg/domain/entities/events.go index de218b285..34a6fe048 100644 --- a/pkg/domain/entities/events.go +++ b/pkg/domain/entities/events.go @@ -14,7 +14,7 @@ type Event struct { // TODO: it would be nice to have full control over the types at some // point and fork such Docker types. dockerEvents.Message - HealthStatus string + HealthStatus string `json:",omitempty"` } // ConvertToLibpodEvent converts an entities event to a libpod one. @@ -34,6 +34,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event { image := e.Actor.Attributes["image"] name := e.Actor.Attributes["name"] details := e.Actor.Attributes + podID := e.Actor.Attributes["podId"] delete(details, "image") delete(details, "name") delete(details, "containerExitCode") @@ -47,6 +48,7 @@ func ConvertToLibpodEvent(e Event) *libpodEvents.Event { Type: t, HealthStatus: e.HealthStatus, Details: libpodEvents.Details{ + PodID: podID, Attributes: details, }, } @@ -61,6 +63,7 @@ func ConvertToEntitiesEvent(e libpodEvents.Event) *Event { attributes["image"] = e.Image attributes["name"] = e.Name attributes["containerExitCode"] = strconv.Itoa(e.ContainerExitCode) + attributes["podId"] = e.PodID message := dockerEvents.Message{ // Compatibility with clients that still look for deprecated API elements Status: e.Status.String(), diff --git a/pkg/domain/infra/abi/terminal/sigproxy_commn.go b/pkg/domain/infra/abi/terminal/sigproxy_commn.go index 3a0132ef3..d42685508 100644 --- a/pkg/domain/infra/abi/terminal/sigproxy_commn.go +++ b/pkg/domain/infra/abi/terminal/sigproxy_commn.go @@ -15,33 +15,25 @@ import ( "github.com/sirupsen/logrus" ) -// Make sure the signal buffer is sufficiently big. -// runc is using the same value. -const signalBufferSize = 2048 - // ProxySignals ... func ProxySignals(ctr *libpod.Container) { // Stop catching the shutdown signals (SIGINT, SIGTERM) - they're going // to the container now. shutdown.Stop() //nolint: errcheck - sigBuffer := make(chan os.Signal, signalBufferSize) + sigBuffer := make(chan os.Signal, signal.SignalBufferSize) signal.CatchAll(sigBuffer) logrus.Debugf("Enabling signal proxying") go func() { for s := range sigBuffer { - // Ignore SIGCHLD and SIGPIPE - these are mostly likely - // intended for the podman command itself. - // SIGURG was added because of golang 1.14 and its preemptive changes - // causing more signals to "show up". - // https://github.com/containers/podman/issues/5483 - if s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG { + syscallSignal := s.(syscall.Signal) + if signal.IsSignalIgnoredBySigProxy(syscallSignal) { continue } - if err := ctr.Kill(uint(s.(syscall.Signal))); err != nil { + if err := ctr.Kill(uint(syscallSignal)); err != nil { if errors.Is(err, define.ErrCtrStateInvalid) { logrus.Infof("Ceasing signal forwarding to container %s as it has stopped", ctr.ID()) } else { diff --git a/pkg/domain/infra/tunnel/containers.go b/pkg/domain/infra/tunnel/containers.go index c82c9ba33..0b573686f 100644 --- a/pkg/domain/infra/tunnel/containers.go +++ b/pkg/domain/infra/tunnel/containers.go @@ -828,6 +828,13 @@ func (ic *ContainerEngine) ContainerRun(ctx context.Context, opts entities.Conta } // Attach + if opts.SigProxy { + remoteProxySignals(con.ID, func(signal string) error { + killOpts := entities.KillOptions{All: false, Latest: false, Signal: signal} + _, err := ic.ContainerKill(ctx, []string{con.ID}, killOpts) + return err + }) + } if err := startAndAttach(ic, con.ID, &opts.DetachKeys, opts.InputStream, opts.OutputStream, opts.ErrorStream); err != nil { if err == define.ErrDetach { return &report, nil diff --git a/pkg/domain/infra/tunnel/runtime.go b/pkg/domain/infra/tunnel/runtime.go index 6542ea5b7..75bd4ef5e 100644 --- a/pkg/domain/infra/tunnel/runtime.go +++ b/pkg/domain/infra/tunnel/runtime.go @@ -2,6 +2,12 @@ package tunnel import ( "context" + "os" + "syscall" + + "github.com/containers/podman/v4/libpod/define" + "github.com/containers/podman/v4/pkg/signal" + "github.com/sirupsen/logrus" ) // Image-related runtime using an ssh-tunnel to utilize Podman service @@ -18,3 +24,28 @@ type ContainerEngine struct { type SystemEngine struct { ClientCtx context.Context } + +func remoteProxySignals(ctrID string, killFunc func(string) error) { + sigBuffer := make(chan os.Signal, signal.SignalBufferSize) + signal.CatchAll(sigBuffer) + + logrus.Debugf("Enabling signal proxying") + + go func() { + for s := range sigBuffer { + syscallSignal := s.(syscall.Signal) + if signal.IsSignalIgnoredBySigProxy(syscallSignal) { + continue + } + signalName, err := signal.ParseSysSignalToName(syscallSignal) + if err != nil { + logrus.Infof("Ceasing signal %v forwarding to container %s as it has stopped: %s", s, ctrID, err) + } + if err := killFunc(signalName); err != nil { + if err.Error() == define.ErrCtrStateInvalid.Error() { + logrus.Debugf("Ceasing signal %q forwarding to container %s as it has stopped", signalName, ctrID) + } + } + } + }() +} diff --git a/pkg/signal/signal_common.go b/pkg/signal/signal_common.go index fc1ecc04d..a81d0461b 100644 --- a/pkg/signal/signal_common.go +++ b/pkg/signal/signal_common.go @@ -9,6 +9,10 @@ import ( "syscall" ) +// Make sure the signal buffer is sufficiently big. +// runc is using the same value. +const SignalBufferSize = 2048 + // ParseSignal translates a string to a valid syscall signal. // It returns an error if the signal map doesn't include the given signal. func ParseSignal(rawSignal string) (syscall.Signal, error) { @@ -56,3 +60,14 @@ func StopCatch(sigc chan os.Signal) { signal.Stop(sigc) close(sigc) } + +// ParseSysSignalToName translates syscall.Signal to its name in the operating system. +// For example, syscall.Signal(9) will return "KILL" on Linux system. +func ParseSysSignalToName(s syscall.Signal) (string, error) { + for k, v := range SignalMap { + if v == s { + return k, nil + } + } + return "", fmt.Errorf("unknown syscall signal: %s", s) +} diff --git a/pkg/signal/signal_common_test.go b/pkg/signal/signal_common_test.go index c4ae6b389..bd9b230f7 100644 --- a/pkg/signal/signal_common_test.go +++ b/pkg/signal/signal_common_test.go @@ -118,3 +118,52 @@ func TestParseSignalNameOrNumber(t *testing.T) { }) } } + +func TestParseSysSignalToName(t *testing.T) { + type args struct { + signal syscall.Signal + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Kill should work", + args: args{ + signal: syscall.SIGKILL, + }, + want: "KILL", + wantErr: false, + }, + { + name: "Non-defined signal number should not work", + args: args{ + signal: 923, + }, + want: "", + wantErr: true, + }, + { + name: "garbage should fail", + args: args{ + signal: -1, + }, + want: "", + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := ParseSysSignalToName(tt.args.signal) + if (err != nil) != tt.wantErr { + t.Errorf("ParseSysSignalToName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("ParseSysSignalToName() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/signal/signal_linux.go b/pkg/signal/signal_linux.go index 5103b6033..81e4ed758 100644 --- a/pkg/signal/signal_linux.go +++ b/pkg/signal/signal_linux.go @@ -89,3 +89,11 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +// IsSignalIgnoredBySigProxy determines whether sig-proxy should ignore syscall signal +func IsSignalIgnoredBySigProxy(s syscall.Signal) bool { + // Ignore SIGCHLD and SIGPIPE - these are most likely intended for the podman command itself. + // SIGURG was added because of golang 1.14 and its preemptive changes causing more signals to "show up". + // https://github.com/containers/podman/issues/5483 + return s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG +} diff --git a/pkg/signal/signal_linux_mipsx.go b/pkg/signal/signal_linux_mipsx.go index cdf9ad4c5..c97eeb23d 100644 --- a/pkg/signal/signal_linux_mipsx.go +++ b/pkg/signal/signal_linux_mipsx.go @@ -90,3 +90,11 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +// IsSignalIgnoredBySigProxy determines whether sig-proxy should ignore syscall signal +func IsSignalIgnoredBySigProxy(s syscall.Signal) bool { + // Ignore SIGCHLD and SIGPIPE - these are most likely intended for the podman command itself. + // SIGURG was added because of golang 1.14 and its preemptive changes causing more signals to "show up". + // https://github.com/containers/podman/issues/5483 + return s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG +} diff --git a/pkg/signal/signal_unix.go b/pkg/signal/signal_unix.go index 7919e3670..01d99d7bc 100644 --- a/pkg/signal/signal_unix.go +++ b/pkg/signal/signal_unix.go @@ -87,3 +87,11 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +// IsSignalIgnoredBySigProxy determines whether sig-proxy should ignore syscall signal +func IsSignalIgnoredBySigProxy(s syscall.Signal) bool { + // Ignore SIGCHLD and SIGPIPE - these are most likely intended for the podman command itself. + // SIGURG was added because of golang 1.14 and its preemptive changes causing more signals to "show up". + // https://github.com/containers/podman/issues/5483 + return s == syscall.SIGCHLD || s == syscall.SIGPIPE || s == syscall.SIGURG +} diff --git a/pkg/signal/signal_unsupported.go b/pkg/signal/signal_unsupported.go index 19ae93a61..590aaf978 100644 --- a/pkg/signal/signal_unsupported.go +++ b/pkg/signal/signal_unsupported.go @@ -87,3 +87,9 @@ var SignalMap = map[string]syscall.Signal{ "RTMAX-1": sigrtmax - 1, "RTMAX": sigrtmax, } + +// IsSignalIgnoredBySigProxy determines whether to sig-proxy should ignore syscall signal +// keep the container running or not. In unsupported OS this should not ignore any syscall signal. +func IsSignalIgnoredBySigProxy(s syscall.Signal) bool { + return false +} diff --git a/pkg/util/utils_freebsd.go b/pkg/util/utils_freebsd.go index 9b0d7c8c7..ba91308af 100644 --- a/pkg/util/utils_freebsd.go +++ b/pkg/util/utils_freebsd.go @@ -13,6 +13,6 @@ func GetContainerPidInformationDescriptors() ([]string, error) { return []string{}, errors.New("this function is not supported on freebsd") } -func AddPrivilegedDevices(g *generate.Generator) error { +func AddPrivilegedDevices(g *generate.Generator, systemdMode bool) error { return nil } diff --git a/pkg/util/utils_linux.go b/pkg/util/utils_linux.go index 7b2d98666..07927db1c 100644 --- a/pkg/util/utils_linux.go +++ b/pkg/util/utils_linux.go @@ -70,7 +70,7 @@ func FindDeviceNodes() (map[string]string, error) { return nodes, nil } -func AddPrivilegedDevices(g *generate.Generator) error { +func AddPrivilegedDevices(g *generate.Generator, systemdMode bool) error { hostDevices, err := getDevices("/dev") if err != nil { return err @@ -104,6 +104,9 @@ func AddPrivilegedDevices(g *generate.Generator) error { } } else { for _, d := range hostDevices { + if systemdMode && strings.HasPrefix(d.Path, "/dev/tty") { + continue + } g.AddDevice(d) } // Add resources device - need to clear the existing one first. |