github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/libpod/util_linux.go (about) 1 // +build linux 2 3 package libpod 4 5 import ( 6 "fmt" 7 "strings" 8 "syscall" 9 10 "github.com/containers/podman/v2/libpod/define" 11 "github.com/containers/podman/v2/pkg/cgroups" 12 "github.com/containers/podman/v2/pkg/rootless" 13 "github.com/opencontainers/selinux/go-selinux/label" 14 "github.com/pkg/errors" 15 "github.com/sirupsen/logrus" 16 "golang.org/x/sys/unix" 17 ) 18 19 // systemdSliceFromPath makes a new systemd slice under the given parent with 20 // the given name. 21 // The parent must be a slice. The name must NOT include ".slice" 22 func systemdSliceFromPath(parent, name string) (string, error) { 23 cgroupPath, err := assembleSystemdCgroupName(parent, name) 24 if err != nil { 25 return "", err 26 } 27 28 logrus.Debugf("Created cgroup path %s for parent %s and name %s", cgroupPath, parent, name) 29 30 if err := makeSystemdCgroup(cgroupPath); err != nil { 31 return "", errors.Wrapf(err, "error creating cgroup %s", cgroupPath) 32 } 33 34 logrus.Debugf("Created cgroup %s", cgroupPath) 35 36 return cgroupPath, nil 37 } 38 39 func getDefaultSystemdCgroup() string { 40 if rootless.IsRootless() { 41 return SystemdDefaultRootlessCgroupParent 42 } 43 return SystemdDefaultCgroupParent 44 } 45 46 // makeSystemdCgroup creates a systemd CGroup at the given location. 47 func makeSystemdCgroup(path string) error { 48 controller, err := cgroups.NewSystemd(getDefaultSystemdCgroup()) 49 if err != nil { 50 return err 51 } 52 53 if rootless.IsRootless() { 54 return controller.CreateSystemdUserUnit(path, rootless.GetRootlessUID()) 55 } 56 return controller.CreateSystemdUnit(path) 57 } 58 59 // deleteSystemdCgroup deletes the systemd cgroup at the given location 60 func deleteSystemdCgroup(path string) error { 61 controller, err := cgroups.NewSystemd(getDefaultSystemdCgroup()) 62 if err != nil { 63 return err 64 } 65 if rootless.IsRootless() { 66 conn, err := cgroups.GetUserConnection(rootless.GetRootlessUID()) 67 if err != nil { 68 return err 69 } 70 defer conn.Close() 71 return controller.DeleteByPathConn(path, conn) 72 } 73 74 return controller.DeleteByPath(path) 75 } 76 77 // assembleSystemdCgroupName creates a systemd cgroup path given a base and 78 // a new component to add. 79 // The base MUST be systemd slice (end in .slice) 80 func assembleSystemdCgroupName(baseSlice, newSlice string) (string, error) { 81 const sliceSuffix = ".slice" 82 83 if !strings.HasSuffix(baseSlice, sliceSuffix) { 84 return "", errors.Wrapf(define.ErrInvalidArg, "cannot assemble cgroup path with base %q - must end in .slice", baseSlice) 85 } 86 87 noSlice := strings.TrimSuffix(baseSlice, sliceSuffix) 88 final := fmt.Sprintf("%s/%s-%s%s", baseSlice, noSlice, newSlice, sliceSuffix) 89 90 return final, nil 91 } 92 93 var lvpRelabel = label.Relabel 94 var lvpInitLabels = label.InitLabels 95 var lvpReleaseLabel = label.ReleaseLabel 96 97 // LabelVolumePath takes a mount path for a volume and gives it an 98 // selinux label of either shared or not 99 func LabelVolumePath(path string) error { 100 _, mountLabel, err := lvpInitLabels([]string{}) 101 if err != nil { 102 return errors.Wrapf(err, "error getting default mountlabels") 103 } 104 if err := lvpReleaseLabel(mountLabel); err != nil { 105 return errors.Wrapf(err, "error releasing label %q", mountLabel) 106 } 107 108 if err := lvpRelabel(path, mountLabel, true); err != nil { 109 if err == syscall.ENOTSUP { 110 logrus.Debugf("Labeling not supported on %q", path) 111 } else { 112 return errors.Wrapf(err, "error setting selinux label for %s to %q as shared", path, mountLabel) 113 } 114 } 115 return nil 116 } 117 118 // Unmount umounts a target directory 119 func Unmount(mount string) { 120 if err := unix.Unmount(mount, unix.MNT_DETACH); err != nil { 121 if err != syscall.EINVAL { 122 logrus.Warnf("failed to unmount %s : %v", mount, err) 123 } else { 124 logrus.Debugf("failed to unmount %s : %v", mount, err) 125 } 126 } 127 }