do not pass volume-opt as bind mounts options to runtime

Starting with runc 1.3.0 it errors when we pass unknown mount options to
the runtime, the volume-opt options are specifc to the volume we create
and should not be passed to the mount in the oci spec.

Fixes: #26938

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2025-09-01 11:44:11 +02:00
parent dedeb24e9f
commit 4e2a04dedc
2 changed files with 24 additions and 7 deletions

View File

@@ -504,6 +504,15 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
_, err := r.state.Volume(vol.Name) _, err := r.state.Volume(vol.Name)
if err == nil { if err == nil {
// The volume exists, we're good // The volume exists, we're good
// Make sure to drop all volume-opt options as they only apply to
// the volume create which we don't do again.
var volOpts []string
for _, opts := range vol.Options {
if !strings.HasPrefix(opts, "volume-opt") {
volOpts = append(volOpts, opts)
}
}
vol.Options = volOpts
continue continue
} else if !errors.Is(err, define.ErrNoSuchVolume) { } else if !errors.Is(err, define.ErrNoSuchVolume) {
return nil, fmt.Errorf("retrieving named volume %s for new container: %w", vol.Name, err) return nil, fmt.Errorf("retrieving named volume %s for new container: %w", vol.Name, err)
@@ -530,6 +539,7 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
if len(vol.Options) > 0 { if len(vol.Options) > 0 {
isDriverOpts := false isDriverOpts := false
driverOpts := make(map[string]string) driverOpts := make(map[string]string)
var volOpts []string
for _, opts := range vol.Options { for _, opts := range vol.Options {
if strings.HasPrefix(opts, "volume-opt") { if strings.HasPrefix(opts, "volume-opt") {
isDriverOpts = true isDriverOpts = true
@@ -538,8 +548,11 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
return nil, err return nil, err
} }
driverOpts[driverOptKey] = driverOptValue driverOpts[driverOptKey] = driverOptValue
} else {
volOpts = append(volOpts, opts)
} }
} }
vol.Options = volOpts
if isDriverOpts { if isDriverOpts {
parsedOptions := []VolumeCreateOption{WithVolumeOptions(driverOpts)} parsedOptions := []VolumeCreateOption{WithVolumeOptions(driverOpts)}
volOptions = append(volOptions, parsedOptions...) volOptions = append(volOptions, parsedOptions...)

View File

@@ -8,6 +8,7 @@ import (
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
. "github.com/containers/podman/v5/test/utils" . "github.com/containers/podman/v5/test/utils"
@@ -859,14 +860,17 @@ VOLUME /test/`, ALPINE)
It("podman run with --mount and named volume with driver-opts", func() { It("podman run with --mount and named volume with driver-opts", func() {
// anonymous volume mount with driver opts // anonymous volume mount with driver opts
vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev" vol := "type=volume,source=test_vol,dst=/test,volume-opt=type=tmpfs,volume-opt=device=tmpfs,volume-opt=o=nodev"
session := podmanTest.Podman([]string{"run", "--rm", "--mount", vol, ALPINE, "echo", "hello"}) // Loop twice to cover both the initial code path that creates the volume and the ones which reuses it.
session.WaitWithDefaultTimeout() for i := range 2 {
Expect(session).Should(ExitCleanly()) name := "testctr" + strconv.Itoa(i)
podmanTest.PodmanExitCleanly("run", "--name", name, "--mount", vol, ALPINE, "echo", "hello")
inspectVol := podmanTest.Podman([]string{"volume", "inspect", "test_vol"}) inspectVol := podmanTest.PodmanExitCleanly("volume", "inspect", "test_vol")
inspectVol.WaitWithDefaultTimeout() Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev"))
Expect(inspectVol).Should(ExitCleanly())
Expect(inspectVol.OutputToString()).To(ContainSubstring("nodev")) inspect := podmanTest.PodmanExitCleanly("container", "inspect", name, "--format", "{{range .Mounts}}{{.Options}}{{end}}")
Expect(inspect.OutputToString()).To(ContainSubstring("[nosuid nodev rbind]"))
}
}) })
It("volume permissions after run", func() { It("volume permissions after run", func() {