diff --git a/run_linux.go b/run_linux.go index 3e3a77739c..5ae546c9bd 100644 --- a/run_linux.go +++ b/run_linux.go @@ -3,6 +3,7 @@ package buildah import ( + "bufio" "context" "errors" "fmt" @@ -1373,7 +1374,17 @@ func setupSpecialMountSpecChanges(spec *specs.Spec, shmSize string) ([]specs.Mou isUserns := isNewUserns || isRootless - if isUserns && !isIpcns { + // Check /proc/filesystems to see if the kernel supports mqueue. + if !isMqueueSupported() { + // The default /dev/mqueue mount would fail with ENODEV, so drop it. + filtered := make([]specs.Mount, 0, len(mounts)) + for _, m := range mounts { + if m.Destination != "/dev/mqueue" { + filtered = append(filtered, m) + } + } + mounts = filtered + } else if isUserns && !isIpcns { devMqueue := "/dev/mqueue" devMqueueMnt := specs.Mount{ Destination: devMqueue, @@ -1429,6 +1440,27 @@ func setupSpecialMountSpecChanges(spec *specs.Spec, shmSize string) ([]specs.Mou return mounts, nil } +// isMqueueSupported reports whether the kernel supports the mqueue +// filesystem, i.e. was built with CONFIG_POSIX_MQUEUE. +var isMqueueSupported = sync.OnceValue(func() bool { + f, err := os.Open("/proc/filesystems") + if err != nil { + return false + } + defer f.Close() + scanner := bufio.NewScanner(f) + for scanner.Scan() { + fields := strings.Fields(scanner.Text()) + if len(fields) > 0 && fields[len(fields)-1] == "mqueue" { + return true + } + } + if err := scanner.Err(); err != nil { + logrus.Warnf("Failed to read /proc/filesystems: %v, assuming mqueue is not supported", err) + } + return false +}) + func checkIDsGreaterThan5(ids []specs.LinuxIDMapping) bool { for _, r := range ids { if r.ContainerID <= 5 && 5 < r.ContainerID+r.Size { diff --git a/run_linux_test.go b/run_linux_test.go new file mode 100644 index 0000000000..a283c49ef0 --- /dev/null +++ b/run_linux_test.go @@ -0,0 +1,36 @@ +//go:build linux + +package buildah + +import ( + "fmt" + "slices" + "testing" + + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-tools/generate" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestSetupSpecialMountSpecChangesMqueue(t *testing.T) { + orig := isMqueueSupported + t.Cleanup(func() { isMqueueSupported = orig }) + + for _, supported := range []bool{true, false} { + t.Run(fmt.Sprintf("mqueue supported=%v", supported), func(t *testing.T) { + isMqueueSupported = func() bool { return supported } + + g, err := generate.New("linux") + require.NoError(t, err) + mounts, err := setupSpecialMountSpecChanges(g.Config, "65536k") + require.NoError(t, err) + + hasMqueue := slices.ContainsFunc(mounts, func(m specs.Mount) bool { + return m.Destination == "/dev/mqueue" + }) + assert.Equal(t, supported, hasMqueue, + "the /dev/mqueue mount should be present if and only if the kernel supports mqueue") + }) + } +}