Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion run_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package buildah

import (
"bufio"
"context"
"errors"
"fmt"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this uses the same function as podman it should be moved to the common library, maybe as a new pkg there pkg/fsinfo or something like that?
So that then podman and buildah can reuse the same function from one place which means we also only have to cache it once.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call, I can take a look.

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 {
Expand Down
36 changes: 36 additions & 0 deletions run_linux_test.go
Original file line number Diff line number Diff line change
@@ -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")
})
}
}