diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/namespaces/namespaces.go | 2 | ||||
-rw-r--r-- | pkg/spec/config_linux.go | 50 | ||||
-rw-r--r-- | pkg/spec/parse.go | 2 | ||||
-rw-r--r-- | pkg/spec/spec.go | 4 |
4 files changed, 54 insertions, 4 deletions
diff --git a/pkg/namespaces/namespaces.go b/pkg/namespaces/namespaces.go index 832efd554..11b47fec4 100644 --- a/pkg/namespaces/namespaces.go +++ b/pkg/namespaces/namespaces.go @@ -84,7 +84,7 @@ func (n UTSMode) Valid() bool { // IpcMode represents the container ipc stack. type IpcMode string -// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared. +// IsPrivate indicates whether the container uses its own private ipc namespace which cannot be shared. func (n IpcMode) IsPrivate() bool { return n == "private" } diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go index 5bf8eff43..f3e200262 100644 --- a/pkg/spec/config_linux.go +++ b/pkg/spec/config_linux.go @@ -3,7 +3,11 @@ package createconfig import ( + "fmt" "io/ioutil" + "os" + "path/filepath" + "strings" "github.com/docker/docker/profiles/seccomp" "github.com/opencontainers/runc/libcontainer/configs" @@ -27,6 +31,52 @@ func Device(d *configs.Device) spec.LinuxDevice { } } +// devicesFromPath computes a list of devices +func devicesFromPath(g *generate.Generator, devicePath string) error { + devs := strings.Split(devicePath, ":") + resolvedDevicePath := devs[0] + // check if it is a symbolic link + if src, err := os.Lstat(resolvedDevicePath); err == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink { + if linkedPathOnHost, err := filepath.EvalSymlinks(resolvedDevicePath); err == nil { + resolvedDevicePath = linkedPathOnHost + } + } + st, err := os.Stat(resolvedDevicePath) + if err != nil { + return errors.Wrapf(err, "cannot stat %s", devicePath) + } + if st.IsDir() { + if len(devs) > 2 { + return errors.Wrapf(unix.EINVAL, "not allowed to specify destination with a directory %s", devicePath) + } + found := false + // mount the internal devices recursively + if err := filepath.Walk(resolvedDevicePath, func(dpath string, f os.FileInfo, e error) error { + + if f.Mode()&os.ModeDevice == os.ModeDevice { + found = true + device := dpath + + if len(devs) > 1 { + device = fmt.Sprintf("%s:%s", dpath, devs[1]) + } + if err := addDevice(g, device); err != nil { + return errors.Wrapf(err, "failed to add %s device", dpath) + } + } + return nil + }); err != nil { + return err + } + if !found { + return errors.Wrapf(unix.EINVAL, "no devices found in %s", devicePath) + } + return nil + } + + return addDevice(g, devicePath) +} + func addDevice(g *generate.Generator, device string) error { src, dst, permissions, err := ParseDevice(device) if err != nil { diff --git a/pkg/spec/parse.go b/pkg/spec/parse.go index 4d20e35d4..d688b8d1b 100644 --- a/pkg/spec/parse.go +++ b/pkg/spec/parse.go @@ -166,7 +166,7 @@ func ParseDevice(device string) (string, string, string, error) { //nolint permissions = arr[1] } else { if arr[1][0] != '/' { - return "", "", "", fmt.Errorf("invalid device mode: %s", arr[2]) + return "", "", "", fmt.Errorf("invalid device mode: %s", arr[1]) } dst = arr[1] } diff --git a/pkg/spec/spec.go b/pkg/spec/spec.go index 05be00864..c90f16f7c 100644 --- a/pkg/spec/spec.go +++ b/pkg/spec/spec.go @@ -235,8 +235,8 @@ func CreateConfigToOCISpec(config *CreateConfig) (*spec.Spec, error) { //nolint } } } else { - for _, device := range config.Devices { - if err := addDevice(&g, device); err != nil { + for _, devicePath := range config.Devices { + if err := devicesFromPath(&g, devicePath); err != nil { return nil, err } } |