diff --git a/pkg/util/utils_linux.go b/pkg/util/utils_linux.go index e1e87c6d6d7f..468524405d3a 100644 --- a/pkg/util/utils_linux.go +++ b/pkg/util/utils_linux.go @@ -5,8 +5,9 @@ import ( "fmt" "io/fs" "os" - "path" "path/filepath" + "strconv" + "strings" "syscall" "github.com/containers/podman/v4/libpod/define" @@ -70,20 +71,23 @@ func FindDeviceNodes() (map[string]string, error) { return nodes, nil } -func isVirtualConsoleDevice(device string) bool { +// isVirtualConsoleDevice returns true if path is a virtual console device +// (/dev/tty\d+). +// The passed path must be clean (filepath.Clean). +func isVirtualConsoleDevice(path string) bool { /* Virtual consoles are of the form `/dev/tty\d+`, any other device such as /dev/tty, ttyUSB0, or ttyACM0 should not be matched. See `man 4 console` for more information. - - NOTE: Matching is done using path.Match even though a regular expression - would have been more accurate. This is because a regular - expression would have required pre-compilation, which would have - increase the startup time needlessly or made the code more complex - than needed. */ - matched, _ := path.Match("/dev/tty[0-9]*", device) - return matched + suffix := strings.TrimPrefix(path, "/dev/tty") + if suffix == path || suffix == "" { + return false + } + + // 16bit because, max. supported TTY devices is 512 in Linux 6.1.5. + _, err := strconv.ParseUint(suffix, 10, 16) + return err == nil } func AddPrivilegedDevices(g *generate.Generator, systemdMode bool) error { diff --git a/pkg/util/utils_linux_test.go b/pkg/util/utils_linux_test.go new file mode 100644 index 000000000000..cde45bcd2312 --- /dev/null +++ b/pkg/util/utils_linux_test.go @@ -0,0 +1,63 @@ +package util + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGetImageConfigStopSignal(t *testing.T) { + // Linux-only because parsing signal names is not supported on non-Linux systems by + // pkg/signal. + stopSignalValidInt, err := GetImageConfig([]string{"STOPSIGNAL 9"}) + require.Nil(t, err) + assert.Equal(t, stopSignalValidInt.StopSignal, "9") + + stopSignalValidString, err := GetImageConfig([]string{"STOPSIGNAL SIGKILL"}) + require.Nil(t, err) + assert.Equal(t, stopSignalValidString.StopSignal, "9") + + _, err = GetImageConfig([]string{"STOPSIGNAL 0"}) + assert.NotNil(t, err) + + _, err = GetImageConfig([]string{"STOPSIGNAL garbage"}) + assert.NotNil(t, err) + + _, err = GetImageConfig([]string{"STOPSIGNAL "}) + assert.NotNil(t, err) +} + +func TestIsVirtualConsoleDevice(t *testing.T) { + testcases := []struct { + expectedResult bool + path string + }{ + { + expectedResult: true, + path: "/dev/tty10", + }, + { + expectedResult: false, + path: "/dev/tty", + }, + { + expectedResult: false, + path: "/dev/ttyUSB0", + }, + + { + expectedResult: false, + path: "/dev/tty0abcd", + }, + } + + for _, tc := range testcases { + t.Run(tc.path, func(t *testing.T) { + result := isVirtualConsoleDevice(tc.path) + if result != tc.expectedResult { + t.Errorf("isVirtualConsoleDevice returned %t, expected %t", result, tc.expectedResult) + } + }) + } +}