summaryrefslogtreecommitdiff
path: root/pkg/spec/config_linux.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/spec/config_linux.go')
-rw-r--r--pkg/spec/config_linux.go371
1 files changed, 0 insertions, 371 deletions
diff --git a/pkg/spec/config_linux.go b/pkg/spec/config_linux.go
deleted file mode 100644
index 319cce61f..000000000
--- a/pkg/spec/config_linux.go
+++ /dev/null
@@ -1,371 +0,0 @@
-// +build linux
-
-package createconfig
-
-import (
- "fmt"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-
- "github.com/containers/podman/v2/pkg/rootless"
- "github.com/opencontainers/runc/libcontainer/configs"
- "github.com/opencontainers/runc/libcontainer/devices"
- spec "github.com/opencontainers/runtime-spec/specs-go"
- "github.com/opencontainers/runtime-tools/generate"
- "github.com/pkg/errors"
- "golang.org/x/sys/unix"
-)
-
-// Device transforms a libcontainer configs.Device to a specs.LinuxDevice object.
-func Device(d *configs.Device) spec.LinuxDevice {
- return spec.LinuxDevice{
- Type: string(d.Type),
- Path: d.Path,
- Major: d.Major,
- Minor: d.Minor,
- FileMode: fmPtr(int64(d.FileMode)),
- UID: u32Ptr(int64(d.Uid)),
- GID: u32Ptr(int64(d.Gid)),
- }
-}
-
-// 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() {
- found := false
- src := resolvedDevicePath
- dest := src
- var devmode string
- if len(devs) > 1 {
- if len(devs[1]) > 0 && devs[1][0] == '/' {
- dest = devs[1]
- } else {
- devmode = devs[1]
- }
- }
- if len(devs) > 2 {
- if devmode != "" {
- return errors.Wrapf(unix.EINVAL, "invalid device specification %s", devicePath)
- }
- devmode = devs[2]
- }
-
- // 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 := fmt.Sprintf("%s:%s", dpath, filepath.Join(dest, strings.TrimPrefix(dpath, src)))
- if devmode != "" {
- device = fmt.Sprintf("%s:%s", device, devmode)
- }
- 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, strings.Join(append([]string{resolvedDevicePath}, devs[1:]...), ":"))
-}
-
-func deviceCgroupRules(g *generate.Generator, deviceCgroupRules []string) error {
- for _, deviceCgroupRule := range deviceCgroupRules {
- if err := validateDeviceCgroupRule(deviceCgroupRule); err != nil {
- return err
- }
- ss := parseDeviceCgroupRule(deviceCgroupRule)
- if len(ss[0]) != 5 {
- return errors.Errorf("invalid device cgroup rule format: '%s'", deviceCgroupRule)
- }
- matches := ss[0]
- var major, minor *int64
- if matches[2] == "*" {
- majorDev := int64(-1)
- major = &majorDev
- } else {
- majorDev, err := strconv.ParseInt(matches[2], 10, 64)
- if err != nil {
- return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
- }
- major = &majorDev
- }
- if matches[3] == "*" {
- minorDev := int64(-1)
- minor = &minorDev
- } else {
- minorDev, err := strconv.ParseInt(matches[2], 10, 64)
- if err != nil {
- return errors.Errorf("invalid major value in device cgroup rule format: '%s'", deviceCgroupRule)
- }
- minor = &minorDev
- }
- g.AddLinuxResourcesDevice(true, matches[1], major, minor, matches[4])
- }
- return nil
-}
-
-func addDevice(g *generate.Generator, device string) error {
- src, dst, permissions, err := ParseDevice(device)
- if err != nil {
- return err
- }
- dev, err := devices.DeviceFromPath(src, permissions)
- if err != nil {
- return errors.Wrapf(err, "%s is not a valid device", src)
- }
- if rootless.IsRootless() {
- if _, err := os.Stat(src); err != nil {
- if os.IsNotExist(err) {
- return errors.Wrapf(err, "the specified device %s doesn't exist", src)
- }
- return errors.Wrapf(err, "stat device %s exist", src)
- }
- perm := "ro"
- if strings.Contains(permissions, "w") {
- perm = "rw"
- }
- devMnt := spec.Mount{
- Destination: dst,
- Type: TypeBind,
- Source: src,
- Options: []string{"slave", "nosuid", "noexec", perm, "rbind"},
- }
- g.Config.Mounts = append(g.Config.Mounts, devMnt)
- return nil
- }
- dev.Path = dst
- linuxdev := spec.LinuxDevice{
- Path: dev.Path,
- Type: string(dev.Type),
- Major: dev.Major,
- Minor: dev.Minor,
- FileMode: &dev.FileMode,
- UID: &dev.Uid,
- GID: &dev.Gid,
- }
- g.AddDevice(linuxdev)
- g.AddLinuxResourcesDevice(true, string(dev.Type), &dev.Major, &dev.Minor, string(dev.Permissions))
- return nil
-}
-
-// based on getDevices from runc (libcontainer/devices/devices.go)
-func getDevices(path string) ([]*configs.Device, error) {
- files, err := ioutil.ReadDir(path)
- if err != nil {
- if rootless.IsRootless() && os.IsPermission(err) {
- return nil, nil
- }
- return nil, err
- }
- out := []*configs.Device{}
- for _, f := range files {
- switch {
- case f.IsDir():
- switch f.Name() {
- // ".lxc" & ".lxd-mounts" added to address https://github.com/lxc/lxd/issues/2825
- case "pts", "shm", "fd", "mqueue", ".lxc", ".lxd-mounts":
- continue
- default:
- sub, err := getDevices(filepath.Join(path, f.Name()))
- if err != nil {
- return nil, err
- }
- if sub != nil {
- out = append(out, sub...)
- }
- continue
- }
- case f.Name() == "console":
- continue
- case f.Mode()&os.ModeSymlink != 0:
- // do not add symlink'd devices to privileged devices
- continue
- }
- device, err := devices.DeviceFromPath(filepath.Join(path, f.Name()), "rwm")
- if err != nil {
- if err == devices.ErrNotADevice {
- continue
- }
- if os.IsNotExist(err) {
- continue
- }
- return nil, err
- }
- out = append(out, device)
- }
- return out, nil
-}
-
-func addPrivilegedDevices(g *generate.Generator) error {
- hostDevices, err := getDevices("/dev")
- if err != nil {
- return err
- }
- g.ClearLinuxDevices()
-
- if rootless.IsRootless() {
- mounts := make(map[string]interface{})
- for _, m := range g.Mounts() {
- mounts[m.Destination] = true
- }
- newMounts := []spec.Mount{}
- for _, d := range hostDevices {
- devMnt := spec.Mount{
- Destination: d.Path,
- Type: TypeBind,
- Source: d.Path,
- Options: []string{"slave", "nosuid", "noexec", "rw", "rbind"},
- }
- if d.Path == "/dev/ptmx" || strings.HasPrefix(d.Path, "/dev/tty") {
- continue
- }
- if _, found := mounts[d.Path]; found {
- continue
- }
- st, err := os.Stat(d.Path)
- if err != nil {
- if err == unix.EPERM {
- continue
- }
- return errors.Wrapf(err, "stat %s", d.Path)
- }
- // Skip devices that the user has not access to.
- if st.Mode()&0007 == 0 {
- continue
- }
- newMounts = append(newMounts, devMnt)
- }
- g.Config.Mounts = append(newMounts, g.Config.Mounts...)
- g.Config.Linux.Resources.Devices = nil
- } else {
- for _, d := range hostDevices {
- g.AddDevice(Device(d))
- }
- // Add resources device - need to clear the existing one first.
- g.Config.Linux.Resources.Devices = nil
- g.AddLinuxResourcesDevice(true, "", nil, nil, "rwm")
- }
-
- return nil
-}
-
-func (c *CreateConfig) createBlockIO() (*spec.LinuxBlockIO, error) {
- var ret *spec.LinuxBlockIO
- bio := &spec.LinuxBlockIO{}
- if c.Resources.BlkioWeight > 0 {
- ret = bio
- bio.Weight = &c.Resources.BlkioWeight
- }
- if len(c.Resources.BlkioWeightDevice) > 0 {
- var lwds []spec.LinuxWeightDevice
- ret = bio
- for _, i := range c.Resources.BlkioWeightDevice {
- wd, err := ValidateweightDevice(i)
- if err != nil {
- return ret, errors.Wrapf(err, "invalid values for blkio-weight-device")
- }
- wdStat, err := GetStatFromPath(wd.Path)
- if err != nil {
- return ret, errors.Wrapf(err, "error getting stat from path %q", wd.Path)
- }
- lwd := spec.LinuxWeightDevice{
- Weight: &wd.Weight,
- }
- lwd.Major = int64(unix.Major(wdStat.Rdev))
- lwd.Minor = int64(unix.Minor(wdStat.Rdev))
- lwds = append(lwds, lwd)
- }
- bio.WeightDevice = lwds
- }
- if len(c.Resources.DeviceReadBps) > 0 {
- ret = bio
- readBps, err := makeThrottleArray(c.Resources.DeviceReadBps, bps)
- if err != nil {
- return ret, err
- }
- bio.ThrottleReadBpsDevice = readBps
- }
- if len(c.Resources.DeviceWriteBps) > 0 {
- ret = bio
- writeBpds, err := makeThrottleArray(c.Resources.DeviceWriteBps, bps)
- if err != nil {
- return ret, err
- }
- bio.ThrottleWriteBpsDevice = writeBpds
- }
- if len(c.Resources.DeviceReadIOps) > 0 {
- ret = bio
- readIOps, err := makeThrottleArray(c.Resources.DeviceReadIOps, iops)
- if err != nil {
- return ret, err
- }
- bio.ThrottleReadIOPSDevice = readIOps
- }
- if len(c.Resources.DeviceWriteIOps) > 0 {
- ret = bio
- writeIOps, err := makeThrottleArray(c.Resources.DeviceWriteIOps, iops)
- if err != nil {
- return ret, err
- }
- bio.ThrottleWriteIOPSDevice = writeIOps
- }
- return ret, nil
-}
-
-func makeThrottleArray(throttleInput []string, rateType int) ([]spec.LinuxThrottleDevice, error) {
- var (
- ltds []spec.LinuxThrottleDevice
- t *throttleDevice
- err error
- )
- for _, i := range throttleInput {
- if rateType == bps {
- t, err = validateBpsDevice(i)
- } else {
- t, err = validateIOpsDevice(i)
- }
- if err != nil {
- return []spec.LinuxThrottleDevice{}, err
- }
- ltdStat, err := GetStatFromPath(t.path)
- if err != nil {
- return ltds, errors.Wrapf(err, "error getting stat from path %q", t.path)
- }
- ltd := spec.LinuxThrottleDevice{
- Rate: t.rate,
- }
- ltd.Major = int64(unix.Major(ltdStat.Rdev))
- ltd.Minor = int64(unix.Minor(ltdStat.Rdev))
- ltds = append(ltds, ltd)
- }
- return ltds, nil
-}
-
-func GetStatFromPath(path string) (unix.Stat_t, error) {
- s := unix.Stat_t{}
- err := unix.Stat(path, &s)
- return s, err
-}