github.com/afbjorklund/moby@v20.10.5+incompatible/oci/devices_linux.go (about) 1 package oci // import "github.com/docker/docker/oci" 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 "strings" 8 9 "github.com/opencontainers/runc/libcontainer/configs" 10 "github.com/opencontainers/runc/libcontainer/devices" 11 specs "github.com/opencontainers/runtime-spec/specs-go" 12 ) 13 14 // Device transforms a libcontainer configs.Device to a specs.LinuxDevice object. 15 func Device(d *configs.Device) specs.LinuxDevice { 16 return specs.LinuxDevice{ 17 Type: string(d.Type), 18 Path: d.Path, 19 Major: d.Major, 20 Minor: d.Minor, 21 FileMode: fmPtr(int64(d.FileMode)), 22 UID: u32Ptr(int64(d.Uid)), 23 GID: u32Ptr(int64(d.Gid)), 24 } 25 } 26 27 func deviceCgroup(d *configs.Device) specs.LinuxDeviceCgroup { 28 return specs.LinuxDeviceCgroup{ 29 Allow: true, 30 Type: string(d.Type), 31 Major: &d.Major, 32 Minor: &d.Minor, 33 Access: string(d.Permissions), 34 } 35 } 36 37 // DevicesFromPath computes a list of devices and device permissions from paths (pathOnHost and pathInContainer) and cgroup permissions. 38 func DevicesFromPath(pathOnHost, pathInContainer, cgroupPermissions string) (devs []specs.LinuxDevice, devPermissions []specs.LinuxDeviceCgroup, err error) { 39 resolvedPathOnHost := pathOnHost 40 41 // check if it is a symbolic link 42 if src, e := os.Lstat(pathOnHost); e == nil && src.Mode()&os.ModeSymlink == os.ModeSymlink { 43 if linkedPathOnHost, e := filepath.EvalSymlinks(pathOnHost); e == nil { 44 resolvedPathOnHost = linkedPathOnHost 45 } 46 } 47 48 device, err := devices.DeviceFromPath(resolvedPathOnHost, cgroupPermissions) 49 // if there was no error, return the device 50 if err == nil { 51 device.Path = pathInContainer 52 return append(devs, Device(device)), append(devPermissions, deviceCgroup(device)), nil 53 } 54 55 // if the device is not a device node 56 // try to see if it's a directory holding many devices 57 if err == devices.ErrNotADevice { 58 59 // check if it is a directory 60 if src, e := os.Stat(resolvedPathOnHost); e == nil && src.IsDir() { 61 62 // mount the internal devices recursively 63 // TODO check if additional errors should be handled or logged 64 _ = filepath.Walk(resolvedPathOnHost, func(dpath string, f os.FileInfo, _ error) error { 65 childDevice, e := devices.DeviceFromPath(dpath, cgroupPermissions) 66 if e != nil { 67 // ignore the device 68 return nil 69 } 70 71 // add the device to userSpecified devices 72 childDevice.Path = strings.Replace(dpath, resolvedPathOnHost, pathInContainer, 1) 73 devs = append(devs, Device(childDevice)) 74 devPermissions = append(devPermissions, deviceCgroup(childDevice)) 75 76 return nil 77 }) 78 } 79 } 80 81 if len(devs) > 0 { 82 return devs, devPermissions, nil 83 } 84 85 return devs, devPermissions, fmt.Errorf("error gathering device information while adding custom device %q: %s", pathOnHost, err) 86 }