mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Bump dependency opencontainers/runc@v1.0.0-rc9
This commit is contained in:
		
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@@ -97,7 +97,7 @@ require (
 | 
				
			|||||||
	github.com/onsi/gomega v1.7.0
 | 
						github.com/onsi/gomega v1.7.0
 | 
				
			||||||
	github.com/opencontainers/go-digest v1.0.0-rc1
 | 
						github.com/opencontainers/go-digest v1.0.0-rc1
 | 
				
			||||||
	github.com/opencontainers/image-spec v1.0.1 // indirect
 | 
						github.com/opencontainers/image-spec v1.0.1 // indirect
 | 
				
			||||||
	github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830
 | 
						github.com/opencontainers/runc v1.0.0-rc9
 | 
				
			||||||
	github.com/opencontainers/runtime-spec v1.0.0 // indirect
 | 
						github.com/opencontainers/runtime-spec v1.0.0 // indirect
 | 
				
			||||||
	github.com/opencontainers/selinux v1.2.2
 | 
						github.com/opencontainers/selinux v1.2.2
 | 
				
			||||||
	github.com/pborman/uuid v1.2.0
 | 
						github.com/pborman/uuid v1.2.0
 | 
				
			||||||
@@ -367,7 +367,7 @@ replace (
 | 
				
			|||||||
	github.com/onsi/gomega => github.com/onsi/gomega v1.7.0
 | 
						github.com/onsi/gomega => github.com/onsi/gomega v1.7.0
 | 
				
			||||||
	github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0-rc1
 | 
						github.com/opencontainers/go-digest => github.com/opencontainers/go-digest v1.0.0-rc1
 | 
				
			||||||
	github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1
 | 
						github.com/opencontainers/image-spec => github.com/opencontainers/image-spec v1.0.1
 | 
				
			||||||
	github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830
 | 
						github.com/opencontainers/runc => github.com/opencontainers/runc v1.0.0-rc9
 | 
				
			||||||
	github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.0
 | 
						github.com/opencontainers/runtime-spec => github.com/opencontainers/runtime-spec v1.0.0
 | 
				
			||||||
	github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.2.2
 | 
						github.com/opencontainers/selinux => github.com/opencontainers/selinux v1.2.2
 | 
				
			||||||
	github.com/pborman/uuid => github.com/pborman/uuid v1.2.0
 | 
						github.com/pborman/uuid => github.com/pborman/uuid v1.2.0
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.sum
									
									
									
									
									
								
							@@ -345,8 +345,8 @@ github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2i
 | 
				
			|||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 | 
					github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 | 
				
			||||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
 | 
					github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
 | 
				
			||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 | 
					github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 | 
				
			||||||
github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830 h1:yvQ/2Pupw60ON8TYEIGGTAI77yZsWYkiOeHFZWkwlCk=
 | 
					github.com/opencontainers/runc v1.0.0-rc9 h1:/k06BMULKF5hidyoZymkoDCzdJzltZpz/UU4LguQVtc=
 | 
				
			||||||
github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 | 
					github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 | 
				
			||||||
github.com/opencontainers/runtime-spec v1.0.0 h1:O6L965K88AilqnxeYPks/75HLpp4IG+FjeSCI3cVdRg=
 | 
					github.com/opencontainers/runtime-spec v1.0.0 h1:O6L965K88AilqnxeYPks/75HLpp4IG+FjeSCI3cVdRg=
 | 
				
			||||||
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 | 
					github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
 | 
				
			||||||
github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4FtGEe8bFg=
 | 
					github.com/opencontainers/selinux v1.2.2 h1:Kx9J6eDG5/24A6DtUquGSpJQ+m2MUTahn4FtGEe8bFg=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -261,6 +261,7 @@ process := &libcontainer.Process{
 | 
				
			|||||||
	Stdin:  os.Stdin,
 | 
						Stdin:  os.Stdin,
 | 
				
			||||||
	Stdout: os.Stdout,
 | 
						Stdout: os.Stdout,
 | 
				
			||||||
	Stderr: os.Stderr,
 | 
						Stderr: os.Stderr,
 | 
				
			||||||
 | 
						Init:   true,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
err := container.Run(process)
 | 
					err := container.Run(process)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										10
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										10
									
								
								vendor/github.com/opencontainers/runc/libcontainer/apparmor/apparmor.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,6 +6,8 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/utils"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// IsEnabled returns true if apparmor is enabled for the host.
 | 
					// IsEnabled returns true if apparmor is enabled for the host.
 | 
				
			||||||
@@ -19,7 +21,7 @@ func IsEnabled() bool {
 | 
				
			|||||||
	return false
 | 
						return false
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setprocattr(attr, value string) error {
 | 
					func setProcAttr(attr, value string) error {
 | 
				
			||||||
	// Under AppArmor you can only change your own attr, so use /proc/self/
 | 
						// Under AppArmor you can only change your own attr, so use /proc/self/
 | 
				
			||||||
	// instead of /proc/<tid>/ like libapparmor does
 | 
						// instead of /proc/<tid>/ like libapparmor does
 | 
				
			||||||
	path := fmt.Sprintf("/proc/self/attr/%s", attr)
 | 
						path := fmt.Sprintf("/proc/self/attr/%s", attr)
 | 
				
			||||||
@@ -30,6 +32,10 @@ func setprocattr(attr, value string) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer f.Close()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := utils.EnsureProcHandle(f); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = fmt.Fprintf(f, "%s", value)
 | 
						_, err = fmt.Fprintf(f, "%s", value)
 | 
				
			||||||
	return err
 | 
						return err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -37,7 +43,7 @@ func setprocattr(attr, value string) error {
 | 
				
			|||||||
// changeOnExec reimplements aa_change_onexec from libapparmor in Go
 | 
					// changeOnExec reimplements aa_change_onexec from libapparmor in Go
 | 
				
			||||||
func changeOnExec(name string) error {
 | 
					func changeOnExec(name string) error {
 | 
				
			||||||
	value := "exec " + name
 | 
						value := "exec " + name
 | 
				
			||||||
	if err := setprocattr("exec", value); err != nil {
 | 
						if err := setProcAttr("exec", value); err != nil {
 | 
				
			||||||
		return fmt.Errorf("apparmor failed to apply profile: %s", err)
 | 
							return fmt.Errorf("apparmor failed to apply profile: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/capabilities_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/capabilities_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -71,7 +71,11 @@ func newContainerCapList(capConfig *configs.Capabilities) (*containerCapabilitie
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		ambient = append(ambient, v)
 | 
							ambient = append(ambient, v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pid, err := capability.NewPid(0)
 | 
						pid, err := capability.NewPid2(0)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = pid.Load()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,19 +6,25 @@ go_library(
 | 
				
			|||||||
        "apply_raw.go",
 | 
					        "apply_raw.go",
 | 
				
			||||||
        "blkio.go",
 | 
					        "blkio.go",
 | 
				
			||||||
        "cpu.go",
 | 
					        "cpu.go",
 | 
				
			||||||
 | 
					        "cpu_v2.go",
 | 
				
			||||||
        "cpuacct.go",
 | 
					        "cpuacct.go",
 | 
				
			||||||
        "cpuset.go",
 | 
					        "cpuset.go",
 | 
				
			||||||
 | 
					        "cpuset_v2.go",
 | 
				
			||||||
        "devices.go",
 | 
					        "devices.go",
 | 
				
			||||||
        "freezer.go",
 | 
					        "freezer.go",
 | 
				
			||||||
 | 
					        "freezer_v2.go",
 | 
				
			||||||
        "fs_unsupported.go",
 | 
					        "fs_unsupported.go",
 | 
				
			||||||
        "hugetlb.go",
 | 
					        "hugetlb.go",
 | 
				
			||||||
 | 
					        "io_v2.go",
 | 
				
			||||||
        "kmem.go",
 | 
					        "kmem.go",
 | 
				
			||||||
        "memory.go",
 | 
					        "memory.go",
 | 
				
			||||||
 | 
					        "memory_v2.go",
 | 
				
			||||||
        "name.go",
 | 
					        "name.go",
 | 
				
			||||||
        "net_cls.go",
 | 
					        "net_cls.go",
 | 
				
			||||||
        "net_prio.go",
 | 
					        "net_prio.go",
 | 
				
			||||||
        "perf_event.go",
 | 
					        "perf_event.go",
 | 
				
			||||||
        "pids.go",
 | 
					        "pids.go",
 | 
				
			||||||
 | 
					        "pids_v2.go",
 | 
				
			||||||
        "utils.go",
 | 
					        "utils.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    importmap = "k8s.io/kubernetes/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs",
 | 
					    importmap = "k8s.io/kubernetes/vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										35
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/apply_raw.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -18,7 +18,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	subsystems = subsystemSet{
 | 
						subsystemsLegacy = subsystemSet{
 | 
				
			||||||
		&CpusetGroup{},
 | 
							&CpusetGroup{},
 | 
				
			||||||
		&DevicesGroup{},
 | 
							&DevicesGroup{},
 | 
				
			||||||
		&MemoryGroup{},
 | 
							&MemoryGroup{},
 | 
				
			||||||
@@ -33,6 +33,14 @@ var (
 | 
				
			|||||||
		&FreezerGroup{},
 | 
							&FreezerGroup{},
 | 
				
			||||||
		&NameGroup{GroupName: "name=systemd", Join: true},
 | 
							&NameGroup{GroupName: "name=systemd", Join: true},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						subsystemsUnified = subsystemSet{
 | 
				
			||||||
 | 
							&CpusetGroupV2{},
 | 
				
			||||||
 | 
							&FreezerGroupV2{},
 | 
				
			||||||
 | 
							&CpuGroupV2{},
 | 
				
			||||||
 | 
							&MemoryGroupV2{},
 | 
				
			||||||
 | 
							&IOGroupV2{},
 | 
				
			||||||
 | 
							&PidsGroupV2{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	HugePageSizes, _ = cgroups.GetHugePageSize()
 | 
						HugePageSizes, _ = cgroups.GetHugePageSize()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -129,6 +137,13 @@ func isIgnorableError(rootless bool, err error) bool {
 | 
				
			|||||||
	return errno == unix.EROFS || errno == unix.EPERM || errno == unix.EACCES
 | 
						return errno == unix.EROFS || errno == unix.EPERM || errno == unix.EACCES
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *Manager) getSubsystems() subsystemSet {
 | 
				
			||||||
 | 
						if cgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							return subsystemsUnified
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return subsystemsLegacy
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Apply(pid int) (err error) {
 | 
					func (m *Manager) Apply(pid int) (err error) {
 | 
				
			||||||
	if m.Cgroups == nil {
 | 
						if m.Cgroups == nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
@@ -158,7 +173,7 @@ func (m *Manager) Apply(pid int) (err error) {
 | 
				
			|||||||
		return cgroups.EnterPid(m.Paths, pid)
 | 
							return cgroups.EnterPid(m.Paths, pid)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, sys := range subsystems {
 | 
						for _, sys := range m.getSubsystems() {
 | 
				
			||||||
		// TODO: Apply should, ideally, be reentrant or be broken up into a separate
 | 
							// TODO: Apply should, ideally, be reentrant or be broken up into a separate
 | 
				
			||||||
		// create and join phase so that the cgroup hierarchy for a container can be
 | 
							// create and join phase so that the cgroup hierarchy for a container can be
 | 
				
			||||||
		// created then join consists of writing the process pids to cgroup.procs
 | 
							// created then join consists of writing the process pids to cgroup.procs
 | 
				
			||||||
@@ -214,7 +229,7 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 | 
				
			|||||||
	defer m.mu.Unlock()
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
	stats := cgroups.NewStats()
 | 
						stats := cgroups.NewStats()
 | 
				
			||||||
	for name, path := range m.Paths {
 | 
						for name, path := range m.Paths {
 | 
				
			||||||
		sys, err := subsystems.Get(name)
 | 
							sys, err := m.getSubsystems().Get(name)
 | 
				
			||||||
		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 | 
							if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -226,14 +241,18 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Set(container *configs.Config) error {
 | 
					func (m *Manager) Set(container *configs.Config) error {
 | 
				
			||||||
 | 
						if container.Cgroups == nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// If Paths are set, then we are just joining cgroups paths
 | 
						// If Paths are set, then we are just joining cgroups paths
 | 
				
			||||||
	// and there is no need to set any values.
 | 
						// and there is no need to set any values.
 | 
				
			||||||
	if m.Cgroups.Paths != nil {
 | 
						if m.Cgroups != nil && m.Cgroups.Paths != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	paths := m.GetPaths()
 | 
						paths := m.GetPaths()
 | 
				
			||||||
	for _, sys := range subsystems {
 | 
						for _, sys := range m.getSubsystems() {
 | 
				
			||||||
		path := paths[sys.Name()]
 | 
							path := paths[sys.Name()]
 | 
				
			||||||
		if err := sys.Set(path, container.Cgroups); err != nil {
 | 
							if err := sys.Set(path, container.Cgroups); err != nil {
 | 
				
			||||||
			if m.Rootless && sys.Name() == "devices" {
 | 
								if m.Rootless && sys.Name() == "devices" {
 | 
				
			||||||
@@ -262,11 +281,15 @@ func (m *Manager) Set(container *configs.Config) error {
 | 
				
			|||||||
// Freeze toggles the container's freezer cgroup depending on the state
 | 
					// Freeze toggles the container's freezer cgroup depending on the state
 | 
				
			||||||
// provided
 | 
					// provided
 | 
				
			||||||
func (m *Manager) Freeze(state configs.FreezerState) error {
 | 
					func (m *Manager) Freeze(state configs.FreezerState) error {
 | 
				
			||||||
 | 
						if m.Cgroups == nil {
 | 
				
			||||||
 | 
							return errors.New("cannot toggle freezer: cgroups not configured for container")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	paths := m.GetPaths()
 | 
						paths := m.GetPaths()
 | 
				
			||||||
	dir := paths["freezer"]
 | 
						dir := paths["freezer"]
 | 
				
			||||||
	prevState := m.Cgroups.Resources.Freezer
 | 
						prevState := m.Cgroups.Resources.Freezer
 | 
				
			||||||
	m.Cgroups.Resources.Freezer = state
 | 
						m.Cgroups.Resources.Freezer = state
 | 
				
			||||||
	freezer, err := subsystems.Get("freezer")
 | 
						freezer, err := m.getSubsystems().Get("freezer")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										92
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpu_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CpuGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "cpu"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) Apply(d *cgroupData) error {
 | 
				
			||||||
 | 
						// We always want to join the cpu group, to allow fair cpu scheduling
 | 
				
			||||||
 | 
						// on a container basis
 | 
				
			||||||
 | 
						path, err := d.path("cpu")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.ApplyDir(path, d.config, d.pid)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) ApplyDir(path string, cgroup *configs.Cgroup, pid int) error {
 | 
				
			||||||
 | 
						// This might happen if we have no cpu cgroup mounted.
 | 
				
			||||||
 | 
						// Just do nothing and don't fail.
 | 
				
			||||||
 | 
						if path == "" {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := os.MkdirAll(path, 0755); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cgroups.WriteCgroupProc(path, pid)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						if cgroup.Resources.CpuWeight != 0 {
 | 
				
			||||||
 | 
							if err := writeFile(path, "cpu.weight", strconv.FormatUint(cgroup.Resources.CpuWeight, 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cgroup.Resources.CpuMax != "" {
 | 
				
			||||||
 | 
							if err := writeFile(path, "cpu.max", cgroup.Resources.CpuMax); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("cpu"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpuGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						f, err := os.Open(filepath.Join(path, "cpu.stat"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc := bufio.NewScanner(f)
 | 
				
			||||||
 | 
						for sc.Scan() {
 | 
				
			||||||
 | 
							t, v, err := getCgroupParamKeyValue(sc.Text())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							switch t {
 | 
				
			||||||
 | 
							case "usage_usec":
 | 
				
			||||||
 | 
								stats.CpuStats.CpuUsage.TotalUsage = v * 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case "user_usec":
 | 
				
			||||||
 | 
								stats.CpuStats.CpuUsage.UsageInUsermode = v * 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case "system_usec":
 | 
				
			||||||
 | 
								stats.CpuStats.CpuUsage.UsageInKernelmode = v * 1000
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										159
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/cpuset_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
						libcontainerUtils "github.com/opencontainers/runc/libcontainer/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CpusetGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "cpuset"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) Apply(d *cgroupData) error {
 | 
				
			||||||
 | 
						dir, err := d.path("cpuset")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.ApplyDir(dir, d.config, d.pid)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						if cgroup.Resources.CpusetCpus != "" {
 | 
				
			||||||
 | 
							if err := writeFile(path, "cpuset.cpus", cgroup.Resources.CpusetCpus); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cgroup.Resources.CpusetMems != "" {
 | 
				
			||||||
 | 
							if err := writeFile(path, "cpuset.mems", cgroup.Resources.CpusetMems); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("cpuset"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) ApplyDir(dir string, cgroup *configs.Cgroup, pid int) error {
 | 
				
			||||||
 | 
						// This might happen if we have no cpuset cgroup mounted.
 | 
				
			||||||
 | 
						// Just do nothing and don't fail.
 | 
				
			||||||
 | 
						if dir == "" {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						mountInfo, err := ioutil.ReadFile("/proc/self/mountinfo")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						root := filepath.Dir(cgroups.GetClosestMountpointAncestor(dir, string(mountInfo)))
 | 
				
			||||||
 | 
						// 'ensureParent' start with parent because we don't want to
 | 
				
			||||||
 | 
						// explicitly inherit from parent, it could conflict with
 | 
				
			||||||
 | 
						// 'cpuset.cpu_exclusive'.
 | 
				
			||||||
 | 
						if err := s.ensureParent(filepath.Dir(dir), root); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := os.MkdirAll(dir, 0755); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// We didn't inherit cpuset configs from parent, but we have
 | 
				
			||||||
 | 
						// to ensure cpuset configs are set before moving task into the
 | 
				
			||||||
 | 
						// cgroup.
 | 
				
			||||||
 | 
						// The logic is, if user specified cpuset configs, use these
 | 
				
			||||||
 | 
						// specified configs, otherwise, inherit from parent. This makes
 | 
				
			||||||
 | 
						// cpuset configs work correctly with 'cpuset.cpu_exclusive', and
 | 
				
			||||||
 | 
						// keep backward compatibility.
 | 
				
			||||||
 | 
						if err := s.ensureCpusAndMems(dir, cgroup); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// because we are not using d.join we need to place the pid into the procs file
 | 
				
			||||||
 | 
						// unlike the other subsystems
 | 
				
			||||||
 | 
						return cgroups.WriteCgroupProc(dir, pid)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) getSubsystemSettings(parent string) (cpus []byte, mems []byte, err error) {
 | 
				
			||||||
 | 
						if cpus, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.cpus.effective")); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if mems, err = ioutil.ReadFile(filepath.Join(parent, "cpuset.mems.effective")); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cpus, mems, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ensureParent makes sure that the parent directory of current is created
 | 
				
			||||||
 | 
					// and populated with the proper cpus and mems files copied from
 | 
				
			||||||
 | 
					// it's parent.
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) ensureParent(current, root string) error {
 | 
				
			||||||
 | 
						parent := filepath.Dir(current)
 | 
				
			||||||
 | 
						if libcontainerUtils.CleanPath(parent) == root {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// Avoid infinite recursion.
 | 
				
			||||||
 | 
						if parent == current {
 | 
				
			||||||
 | 
							return fmt.Errorf("cpuset: cgroup parent path outside cgroup root")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := s.ensureParent(parent, root); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := os.MkdirAll(current, 0755); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.copyIfNeeded(current, parent)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// copyIfNeeded copies the cpuset.cpus and cpuset.mems from the parent
 | 
				
			||||||
 | 
					// directory to the current directory if the file's contents are 0
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) copyIfNeeded(current, parent string) error {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							err                      error
 | 
				
			||||||
 | 
							currentCpus, currentMems []byte
 | 
				
			||||||
 | 
							parentCpus, parentMems   []byte
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if currentCpus, currentMems, err = s.getSubsystemSettings(current); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if parentCpus, parentMems, err = s.getSubsystemSettings(parent); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if s.isEmpty(currentCpus) {
 | 
				
			||||||
 | 
							if err := writeFile(current, "cpuset.cpus", string(parentCpus)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if s.isEmpty(currentMems) {
 | 
				
			||||||
 | 
							if err := writeFile(current, "cpuset.mems", string(parentMems)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) isEmpty(b []byte) bool {
 | 
				
			||||||
 | 
						return len(bytes.Trim(b, "\n")) == 0
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *CpusetGroupV2) ensureCpusAndMems(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						if err := s.Set(path, cgroup); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.copyIfNeeded(path, filepath.Dir(path))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										74
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/freezer_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,74 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type FreezerGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *FreezerGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "freezer"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *FreezerGroupV2) Apply(d *cgroupData) error {
 | 
				
			||||||
 | 
						_, err := d.join("freezer")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *FreezerGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						var desiredState string
 | 
				
			||||||
 | 
						filename := "cgroup.freeze"
 | 
				
			||||||
 | 
						if cgroup.Resources.Freezer == configs.Frozen {
 | 
				
			||||||
 | 
							desiredState = "1"
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							desiredState = "0"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						switch cgroup.Resources.Freezer {
 | 
				
			||||||
 | 
						case configs.Frozen, configs.Thawed:
 | 
				
			||||||
 | 
							for {
 | 
				
			||||||
 | 
								// In case this loop does not exit because it doesn't get the expected
 | 
				
			||||||
 | 
								// state, let's write again this state, hoping it's going to be properly
 | 
				
			||||||
 | 
								// set this time. Otherwise, this loop could run infinitely, waiting for
 | 
				
			||||||
 | 
								// a state change that would never happen.
 | 
				
			||||||
 | 
								if err := writeFile(path, filename, desiredState); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								state, err := readFile(path, filename)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if strings.TrimSpace(state) == desiredState {
 | 
				
			||||||
 | 
									break
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								time.Sleep(1 * time.Millisecond)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						case configs.Undefined:
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return fmt.Errorf("Invalid argument '%s' to freezer.state", string(cgroup.Resources.Freezer))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *FreezerGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("freezer"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *FreezerGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										191
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/io_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/io_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,191 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type IOGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "blkio"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) Apply(d *cgroupData) error {
 | 
				
			||||||
 | 
						_, err := d.join("blkio")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						cgroupsv2 := cgroups.IsCgroup2UnifiedMode()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cgroup.Resources.BlkioWeight != 0 {
 | 
				
			||||||
 | 
							filename := "blkio.weight"
 | 
				
			||||||
 | 
							if cgroupsv2 {
 | 
				
			||||||
 | 
								filename = "io.bfq.weight"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := writeFile(path, filename, strconv.FormatUint(uint64(cgroup.Resources.BlkioWeight), 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cgroup.Resources.BlkioLeafWeight != 0 {
 | 
				
			||||||
 | 
							if err := writeFile(path, "blkio.leaf_weight", strconv.FormatUint(uint64(cgroup.Resources.BlkioLeafWeight), 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, wd := range cgroup.Resources.BlkioWeightDevice {
 | 
				
			||||||
 | 
							if err := writeFile(path, "blkio.weight_device", wd.WeightString()); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := writeFile(path, "blkio.leaf_weight_device", wd.LeafWeightString()); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, td := range cgroup.Resources.BlkioThrottleReadBpsDevice {
 | 
				
			||||||
 | 
							if cgroupsv2 {
 | 
				
			||||||
 | 
								if err := writeFile(path, "io.max", td.StringName("rbps")); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if err := writeFile(path, "blkio.throttle.read_bps_device", td.String()); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, td := range cgroup.Resources.BlkioThrottleWriteBpsDevice {
 | 
				
			||||||
 | 
							if cgroupsv2 {
 | 
				
			||||||
 | 
								if err := writeFile(path, "io.max", td.StringName("wbps")); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if err := writeFile(path, "blkio.throttle.write_bps_device", td.String()); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, td := range cgroup.Resources.BlkioThrottleReadIOPSDevice {
 | 
				
			||||||
 | 
							if cgroupsv2 {
 | 
				
			||||||
 | 
								if err := writeFile(path, "io.max", td.StringName("riops")); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if err := writeFile(path, "blkio.throttle.read_iops_device", td.String()); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, td := range cgroup.Resources.BlkioThrottleWriteIOPSDevice {
 | 
				
			||||||
 | 
							if cgroupsv2 {
 | 
				
			||||||
 | 
								if err := writeFile(path, "io.max", td.StringName("wiops")); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if err := writeFile(path, "blkio.throttle.write_iops_device", td.String()); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("blkio"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func readCgroup2MapFile(path string, name string) (map[string][]string, error) {
 | 
				
			||||||
 | 
						ret := map[string][]string{}
 | 
				
			||||||
 | 
						p := filepath.Join("/sys/fs/cgroup", path, name)
 | 
				
			||||||
 | 
						f, err := os.Open(p)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return ret, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer f.Close()
 | 
				
			||||||
 | 
						scanner := bufio.NewScanner(f)
 | 
				
			||||||
 | 
						for scanner.Scan() {
 | 
				
			||||||
 | 
							line := scanner.Text()
 | 
				
			||||||
 | 
							parts := strings.Fields(line)
 | 
				
			||||||
 | 
							if len(parts) < 2 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ret[parts[0]] = parts[1:]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := scanner.Err(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ret, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) getCgroupV2Stats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						// more details on the io.stat file format: https://www.kernel.org/doc/Documentation/cgroup-v2.txt
 | 
				
			||||||
 | 
						var ioServiceBytesRecursive []cgroups.BlkioStatEntry
 | 
				
			||||||
 | 
						values, err := readCgroup2MapFile(path, "io.stat")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for k, v := range values {
 | 
				
			||||||
 | 
							d := strings.Split(k, ":")
 | 
				
			||||||
 | 
							if len(d) != 2 {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							minor, err := strconv.ParseUint(d[0], 10, 0)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							major, err := strconv.ParseUint(d[1], 10, 0)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, item := range v {
 | 
				
			||||||
 | 
								d := strings.Split(item, "=")
 | 
				
			||||||
 | 
								if len(d) != 2 {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								op := d[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Accommodate the cgroup v1 naming
 | 
				
			||||||
 | 
								switch op {
 | 
				
			||||||
 | 
								case "rbytes":
 | 
				
			||||||
 | 
									op = "read"
 | 
				
			||||||
 | 
								case "wbytes":
 | 
				
			||||||
 | 
									op = "write"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								value, err := strconv.ParseUint(d[1], 10, 0)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								entry := cgroups.BlkioStatEntry{
 | 
				
			||||||
 | 
									Op:    op,
 | 
				
			||||||
 | 
									Major: major,
 | 
				
			||||||
 | 
									Minor: minor,
 | 
				
			||||||
 | 
									Value: value,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								ioServiceBytesRecursive = append(ioServiceBytesRecursive, entry)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stats.BlkioStats = cgroups.BlkioStats{IoServiceBytesRecursive: ioServiceBytesRecursive}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *IOGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						return s.getCgroupV2Stats(path, stats)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										164
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/memory_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,164 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type MemoryGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *MemoryGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "memory"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *MemoryGroupV2) Apply(d *cgroupData) (err error) {
 | 
				
			||||||
 | 
						path, err := d.path("memory")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						} else if path == "" {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if memoryAssigned(d.config) {
 | 
				
			||||||
 | 
							if _, err := os.Stat(path); os.IsNotExist(err) {
 | 
				
			||||||
 | 
								if err := os.MkdirAll(path, 0755); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								// Only enable kernel memory accouting when this cgroup
 | 
				
			||||||
 | 
								// is created by libcontainer, otherwise we might get
 | 
				
			||||||
 | 
								// error when people use `cgroupsPath` to join an existed
 | 
				
			||||||
 | 
								// cgroup whose kernel memory is not initialized.
 | 
				
			||||||
 | 
								if err := EnableKernelMemoryAccounting(path); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								os.RemoveAll(path)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We need to join memory cgroup after set memory limits, because
 | 
				
			||||||
 | 
						// kmem.limit_in_bytes can only be set when the cgroup is empty.
 | 
				
			||||||
 | 
						_, err = d.join("memory")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func setMemoryAndSwapCgroups(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						if cgroup.Resources.MemorySwap != 0 {
 | 
				
			||||||
 | 
							if err := writeFile(path, "memory.swap.max", strconv.FormatInt(cgroup.Resources.MemorySwap, 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cgroup.Resources.Memory != 0 {
 | 
				
			||||||
 | 
							if err := writeFile(path, "memory.max", strconv.FormatInt(cgroup.Resources.Memory, 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *MemoryGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := setMemoryAndSwapCgroups(path, cgroup); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cgroup.Resources.KernelMemory != 0 {
 | 
				
			||||||
 | 
							if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if cgroup.Resources.MemoryReservation != 0 {
 | 
				
			||||||
 | 
							if err := writeFile(path, "memory.high", strconv.FormatInt(cgroup.Resources.MemoryReservation, 10)); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *MemoryGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("memory"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *MemoryGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						// Set stats from memory.stat.
 | 
				
			||||||
 | 
						statsFile, err := os.Open(filepath.Join(path, "memory.stat"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer statsFile.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sc := bufio.NewScanner(statsFile)
 | 
				
			||||||
 | 
						for sc.Scan() {
 | 
				
			||||||
 | 
							t, v, err := getCgroupParamKeyValue(sc.Text())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("failed to parse memory.stat (%q) - %v", sc.Text(), err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							stats.MemoryStats.Stats[t] = v
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stats.MemoryStats.Cache = stats.MemoryStats.Stats["cache"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						memoryUsage, err := getMemoryDataV2(path, "")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stats.MemoryStats.Usage = memoryUsage
 | 
				
			||||||
 | 
						swapUsage, err := getMemoryDataV2(path, "swap")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						stats.MemoryStats.SwapUsage = swapUsage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats.MemoryStats.UseHierarchy = true
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getMemoryDataV2(path, name string) (cgroups.MemoryData, error) {
 | 
				
			||||||
 | 
						memoryData := cgroups.MemoryData{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						moduleName := "memory"
 | 
				
			||||||
 | 
						if name != "" {
 | 
				
			||||||
 | 
							moduleName = strings.Join([]string{"memory", name}, ".")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						usage := strings.Join([]string{moduleName, "current"}, ".")
 | 
				
			||||||
 | 
						limit := strings.Join([]string{moduleName, "max"}, ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value, err := getCgroupParamUint(path, usage)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if moduleName != "memory" && os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return cgroups.MemoryData{}, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", usage, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memoryData.Usage = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						value, err = getCgroupParamUint(path, limit)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if moduleName != "memory" && os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return cgroups.MemoryData{}, nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return cgroups.MemoryData{}, fmt.Errorf("failed to parse %s - %v", limit, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						memoryData.Limit = value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return memoryData, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										107
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/pids_v2.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
				
			|||||||
 | 
					// +build linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PidsGroupV2 struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *PidsGroupV2) Name() string {
 | 
				
			||||||
 | 
						return "pids"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *PidsGroupV2) Apply(d *cgroupData) error {
 | 
				
			||||||
 | 
						_, err := d.join("pids")
 | 
				
			||||||
 | 
						if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *PidsGroupV2) Set(path string, cgroup *configs.Cgroup) error {
 | 
				
			||||||
 | 
						if cgroup.Resources.PidsLimit != 0 {
 | 
				
			||||||
 | 
							// "max" is the fallback value.
 | 
				
			||||||
 | 
							limit := "max"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if cgroup.Resources.PidsLimit > 0 {
 | 
				
			||||||
 | 
								limit = strconv.FormatInt(cgroup.Resources.PidsLimit, 10)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := writeFile(path, "pids.max", limit); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *PidsGroupV2) Remove(d *cgroupData) error {
 | 
				
			||||||
 | 
						return removePath(d.path("pids"))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isNOTSUP(err error) bool {
 | 
				
			||||||
 | 
						switch err := err.(type) {
 | 
				
			||||||
 | 
						case *os.PathError:
 | 
				
			||||||
 | 
							return err.Err == unix.ENOTSUP
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *PidsGroupV2) GetStats(path string, stats *cgroups.Stats) error {
 | 
				
			||||||
 | 
						current, err := getCgroupParamUint(path, "pids.current")
 | 
				
			||||||
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
 | 
							// if the controller is not enabled, let's read the list
 | 
				
			||||||
 | 
							// PIDs (or threads if cgroup.threads is enabled)
 | 
				
			||||||
 | 
							contents, err := ioutil.ReadFile(filepath.Join(path, "cgroup.procs"))
 | 
				
			||||||
 | 
							if err != nil && isNOTSUP(err) {
 | 
				
			||||||
 | 
								contents, err = ioutil.ReadFile(filepath.Join(path, "cgroup.threads"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pids := make(map[string]string)
 | 
				
			||||||
 | 
							for _, i := range strings.Split(string(contents), "\n") {
 | 
				
			||||||
 | 
								if i != "" {
 | 
				
			||||||
 | 
									pids[i] = i
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							stats.PidsStats.Current = uint64(len(pids))
 | 
				
			||||||
 | 
							stats.PidsStats.Limit = 0
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to parse pids.current - %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						maxString, err := getCgroupParamString(path, "pids.max")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to parse pids.max - %s", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Default if pids.max == "max" is 0 -- which represents "no limit".
 | 
				
			||||||
 | 
						var max uint64
 | 
				
			||||||
 | 
						if maxString != "max" {
 | 
				
			||||||
 | 
							max, err = parseUint(maxString, 10, 64)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return fmt.Errorf("failed to parse pids.max - unable to parse %q as a uint from Cgroup file %q", maxString, filepath.Join(path, "pids.max"))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats.PidsStats.Current = current
 | 
				
			||||||
 | 
						stats.PidsStats.Limit = max
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										7
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -6,6 +6,7 @@ import (
 | 
				
			|||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
@@ -59,8 +60,12 @@ func getCgroupParamUint(cgroupPath, cgroupFile string) (uint64, error) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return 0, err
 | 
							return 0, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						trimmed := strings.TrimSpace(string(contents))
 | 
				
			||||||
 | 
						if trimmed == "max" {
 | 
				
			||||||
 | 
							return math.MaxUint64, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	res, err := parseUint(strings.TrimSpace(string(contents)), 10, 64)
 | 
						res, err := parseUint(trimmed, 10, 64)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName)
 | 
							return res, fmt.Errorf("unable to parse %q as a uint from Cgroup file %q", string(contents), fileName)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,6 +5,7 @@ go_library(
 | 
				
			|||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
        "apply_nosystemd.go",
 | 
					        "apply_nosystemd.go",
 | 
				
			||||||
        "apply_systemd.go",
 | 
					        "apply_systemd.go",
 | 
				
			||||||
 | 
					        "unified_hierarchy.go",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
    importmap = "k8s.io/kubernetes/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd",
 | 
					    importmap = "k8s.io/kubernetes/vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd",
 | 
				
			||||||
    importpath = "github.com/opencontainers/runc/libcontainer/cgroups/systemd",
 | 
					    importpath = "github.com/opencontainers/runc/libcontainer/cgroups/systemd",
 | 
				
			||||||
@@ -28,7 +29,6 @@ go_library(
 | 
				
			|||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "@io_bazel_rules_go//go/platform:linux": [
 | 
					        "@io_bazel_rules_go//go/platform:linux": [
 | 
				
			||||||
            "//vendor/github.com/coreos/go-systemd/dbus:go_default_library",
 | 
					            "//vendor/github.com/coreos/go-systemd/dbus:go_default_library",
 | 
				
			||||||
            "//vendor/github.com/coreos/go-systemd/util:go_default_library",
 | 
					 | 
				
			||||||
            "//vendor/github.com/godbus/dbus:go_default_library",
 | 
					            "//vendor/github.com/godbus/dbus:go_default_library",
 | 
				
			||||||
            "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
 | 
					            "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
 | 
				
			||||||
            "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
 | 
					            "//vendor/github.com/opencontainers/runc/libcontainer/cgroups/fs:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										136
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										136
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/apply_systemd.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -14,7 +14,6 @@ import (
 | 
				
			|||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	systemdDbus "github.com/coreos/go-systemd/dbus"
 | 
						systemdDbus "github.com/coreos/go-systemd/dbus"
 | 
				
			||||||
	systemdUtil "github.com/coreos/go-systemd/util"
 | 
					 | 
				
			||||||
	"github.com/godbus/dbus"
 | 
						"github.com/godbus/dbus"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
				
			||||||
@@ -22,7 +21,7 @@ import (
 | 
				
			|||||||
	"github.com/sirupsen/logrus"
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Manager struct {
 | 
					type LegacyManager struct {
 | 
				
			||||||
	mu      sync.Mutex
 | 
						mu      sync.Mutex
 | 
				
			||||||
	Cgroups *configs.Cgroup
 | 
						Cgroups *configs.Cgroup
 | 
				
			||||||
	Paths   map[string]string
 | 
						Paths   map[string]string
 | 
				
			||||||
@@ -50,7 +49,7 @@ func (s subsystemSet) Get(name string) (subsystem, error) {
 | 
				
			|||||||
	return nil, errSubsystemDoesNotExist
 | 
						return nil, errSubsystemDoesNotExist
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var subsystems = subsystemSet{
 | 
					var legacySubsystems = subsystemSet{
 | 
				
			||||||
	&fs.CpusetGroup{},
 | 
						&fs.CpusetGroup{},
 | 
				
			||||||
	&fs.DevicesGroup{},
 | 
						&fs.DevicesGroup{},
 | 
				
			||||||
	&fs.MemoryGroup{},
 | 
						&fs.MemoryGroup{},
 | 
				
			||||||
@@ -74,9 +73,6 @@ const (
 | 
				
			|||||||
var (
 | 
					var (
 | 
				
			||||||
	connLock sync.Mutex
 | 
						connLock sync.Mutex
 | 
				
			||||||
	theConn  *systemdDbus.Conn
 | 
						theConn  *systemdDbus.Conn
 | 
				
			||||||
	hasStartTransientUnit      bool
 | 
					 | 
				
			||||||
	hasStartTransientSliceUnit bool
 | 
					 | 
				
			||||||
	hasDelegateSlice           bool
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newProp(name string, units interface{}) systemdDbus.Property {
 | 
					func newProp(name string, units interface{}) systemdDbus.Property {
 | 
				
			||||||
@@ -86,8 +82,23 @@ func newProp(name string, units interface{}) systemdDbus.Property {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NOTE: This function comes from package github.com/coreos/go-systemd/util
 | 
				
			||||||
 | 
					// It was borrowed here to avoid a dependency on cgo.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// IsRunningSystemd checks whether the host was booted with systemd as its init
 | 
				
			||||||
 | 
					// system. This functions similarly to systemd's `sd_booted(3)`: internally, it
 | 
				
			||||||
 | 
					// checks whether /run/systemd/system/ exists and is a directory.
 | 
				
			||||||
 | 
					// http://www.freedesktop.org/software/systemd/man/sd_booted.html
 | 
				
			||||||
 | 
					func isRunningSystemd() bool {
 | 
				
			||||||
 | 
						fi, err := os.Lstat("/run/systemd/system")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fi.IsDir()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UseSystemd() bool {
 | 
					func UseSystemd() bool {
 | 
				
			||||||
	if !systemdUtil.IsRunningSystemd() {
 | 
						if !isRunningSystemd() {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -100,82 +111,31 @@ func UseSystemd() bool {
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return false
 | 
								return false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Assume we have StartTransientUnit
 | 
					 | 
				
			||||||
		hasStartTransientUnit = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// But if we get UnknownMethod error we don't
 | 
					 | 
				
			||||||
		if _, err := theConn.StartTransientUnit("test.scope", "invalid", nil, nil); err != nil {
 | 
					 | 
				
			||||||
			if dbusError, ok := err.(dbus.Error); ok {
 | 
					 | 
				
			||||||
				if dbusError.Name == "org.freedesktop.DBus.Error.UnknownMethod" {
 | 
					 | 
				
			||||||
					hasStartTransientUnit = false
 | 
					 | 
				
			||||||
					return hasStartTransientUnit
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
			}
 | 
						return true
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Assume we have the ability to start a transient unit as a slice
 | 
					 | 
				
			||||||
		// This was broken until systemd v229, but has been back-ported on RHEL environments >= 219
 | 
					 | 
				
			||||||
		// For details, see: https://bugzilla.redhat.com/show_bug.cgi?id=1370299
 | 
					 | 
				
			||||||
		hasStartTransientSliceUnit = true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// To ensure simple clean-up, we create a slice off the root with no hierarchy
 | 
					 | 
				
			||||||
		slice := fmt.Sprintf("libcontainer_%d_systemd_test_default.slice", os.Getpid())
 | 
					 | 
				
			||||||
		if _, err := theConn.StartTransientUnit(slice, "replace", nil, nil); err != nil {
 | 
					 | 
				
			||||||
			if _, ok := err.(dbus.Error); ok {
 | 
					 | 
				
			||||||
				hasStartTransientSliceUnit = false
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		for i := 0; i <= testSliceWait; i++ {
 | 
					 | 
				
			||||||
			if _, err := theConn.StopUnit(slice, "replace", nil); err != nil {
 | 
					 | 
				
			||||||
				if dbusError, ok := err.(dbus.Error); ok {
 | 
					 | 
				
			||||||
					if strings.Contains(dbusError.Name, "org.freedesktop.systemd1.NoSuchUnit") {
 | 
					 | 
				
			||||||
						hasStartTransientSliceUnit = false
 | 
					 | 
				
			||||||
						break
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				break
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			time.Sleep(time.Millisecond)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Not critical because of the stop unit logic above.
 | 
					 | 
				
			||||||
		theConn.StopUnit(slice, "replace", nil)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Assume StartTransientUnit on a slice allows Delegate
 | 
					 | 
				
			||||||
		hasDelegateSlice = true
 | 
					 | 
				
			||||||
		dlSlice := newProp("Delegate", true)
 | 
					 | 
				
			||||||
		if _, err := theConn.StartTransientUnit(slice, "replace", []systemdDbus.Property{dlSlice}, nil); err != nil {
 | 
					 | 
				
			||||||
			if dbusError, ok := err.(dbus.Error); ok {
 | 
					 | 
				
			||||||
				// Starting with systemd v237, Delegate is not even a property of slices anymore,
 | 
					 | 
				
			||||||
				// so the D-Bus call fails with "InvalidArgs" error.
 | 
					 | 
				
			||||||
				if strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.PropertyReadOnly") || strings.Contains(dbusError.Name, "org.freedesktop.DBus.Error.InvalidArgs") {
 | 
					 | 
				
			||||||
					hasDelegateSlice = false
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// Not critical because of the stop unit logic above.
 | 
					 | 
				
			||||||
		theConn.StopUnit(slice, "replace", nil)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return hasStartTransientUnit
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewSystemdCgroupsManager() (func(config *configs.Cgroup, paths map[string]string) cgroups.Manager, error) {
 | 
					func NewSystemdCgroupsManager() (func(config *configs.Cgroup, paths map[string]string) cgroups.Manager, error) {
 | 
				
			||||||
	if !systemdUtil.IsRunningSystemd() {
 | 
						if !isRunningSystemd() {
 | 
				
			||||||
		return nil, fmt.Errorf("systemd not running on this host, can't use systemd as a cgroups.Manager")
 | 
							return nil, fmt.Errorf("systemd not running on this host, can't use systemd as a cgroups.Manager")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if cgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
		return func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
 | 
							return func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
 | 
				
			||||||
		return &Manager{
 | 
								return &UnifiedManager{
 | 
				
			||||||
 | 
									Cgroups: config,
 | 
				
			||||||
 | 
									Paths:   paths,
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return func(config *configs.Cgroup, paths map[string]string) cgroups.Manager {
 | 
				
			||||||
 | 
							return &LegacyManager{
 | 
				
			||||||
			Cgroups: config,
 | 
								Cgroups: config,
 | 
				
			||||||
			Paths:   paths,
 | 
								Paths:   paths,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Apply(pid int) error {
 | 
					func (m *LegacyManager) Apply(pid int) error {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		c          = m.Cgroups
 | 
							c          = m.Cgroups
 | 
				
			||||||
		unitName   = getUnitName(c)
 | 
							unitName   = getUnitName(c)
 | 
				
			||||||
@@ -208,10 +168,6 @@ func (m *Manager) Apply(pid int) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// if we create a slice, the parent is defined via a Wants=
 | 
						// if we create a slice, the parent is defined via a Wants=
 | 
				
			||||||
	if strings.HasSuffix(unitName, ".slice") {
 | 
						if strings.HasSuffix(unitName, ".slice") {
 | 
				
			||||||
		// This was broken until systemd v229, but has been back-ported on RHEL environments >= 219
 | 
					 | 
				
			||||||
		if !hasStartTransientSliceUnit {
 | 
					 | 
				
			||||||
			return fmt.Errorf("systemd version does not support ability to start a slice as transient unit")
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		properties = append(properties, systemdDbus.PropWants(slice))
 | 
							properties = append(properties, systemdDbus.PropWants(slice))
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// otherwise, we use Slice=
 | 
							// otherwise, we use Slice=
 | 
				
			||||||
@@ -224,12 +180,7 @@ func (m *Manager) Apply(pid int) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check if we can delegate. This is only supported on systemd versions 218 and above.
 | 
						// Check if we can delegate. This is only supported on systemd versions 218 and above.
 | 
				
			||||||
	if strings.HasSuffix(unitName, ".slice") {
 | 
						if !strings.HasSuffix(unitName, ".slice") {
 | 
				
			||||||
		if hasDelegateSlice {
 | 
					 | 
				
			||||||
			// systemd 237 and above no longer allows delegation on a slice
 | 
					 | 
				
			||||||
			properties = append(properties, newProp("Delegate", true))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		// Assume scopes always support delegation.
 | 
							// Assume scopes always support delegation.
 | 
				
			||||||
		properties = append(properties, newProp("Delegate", true))
 | 
							properties = append(properties, newProp("Delegate", true))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -310,7 +261,7 @@ func (m *Manager) Apply(pid int) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	paths := make(map[string]string)
 | 
						paths := make(map[string]string)
 | 
				
			||||||
	for _, s := range subsystems {
 | 
						for _, s := range legacySubsystems {
 | 
				
			||||||
		subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name())
 | 
							subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name())
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 | 
								// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 | 
				
			||||||
@@ -325,7 +276,7 @@ func (m *Manager) Apply(pid int) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Destroy() error {
 | 
					func (m *LegacyManager) Destroy() error {
 | 
				
			||||||
	if m.Cgroups.Paths != nil {
 | 
						if m.Cgroups.Paths != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -339,7 +290,7 @@ func (m *Manager) Destroy() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) GetPaths() map[string]string {
 | 
					func (m *LegacyManager) GetPaths() map[string]string {
 | 
				
			||||||
	m.mu.Lock()
 | 
						m.mu.Lock()
 | 
				
			||||||
	paths := m.Paths
 | 
						paths := m.Paths
 | 
				
			||||||
	m.mu.Unlock()
 | 
						m.mu.Unlock()
 | 
				
			||||||
@@ -351,6 +302,7 @@ func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := os.MkdirAll(path, 0755); err != nil {
 | 
						if err := os.MkdirAll(path, 0755); err != nil {
 | 
				
			||||||
		return "", err
 | 
							return "", err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -361,7 +313,7 @@ func join(c *configs.Cgroup, subsystem string, pid int) (string, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func joinCgroups(c *configs.Cgroup, pid int) error {
 | 
					func joinCgroups(c *configs.Cgroup, pid int) error {
 | 
				
			||||||
	for _, sys := range subsystems {
 | 
						for _, sys := range legacySubsystems {
 | 
				
			||||||
		name := sys.Name()
 | 
							name := sys.Name()
 | 
				
			||||||
		switch name {
 | 
							switch name {
 | 
				
			||||||
		case "name=systemd":
 | 
							case "name=systemd":
 | 
				
			||||||
@@ -456,14 +408,14 @@ func getSubsystemPath(c *configs.Cgroup, subsystem string) (string, error) {
 | 
				
			|||||||
	return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
 | 
						return filepath.Join(mountpoint, initPath, slice, getUnitName(c)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Freeze(state configs.FreezerState) error {
 | 
					func (m *LegacyManager) Freeze(state configs.FreezerState) error {
 | 
				
			||||||
	path, err := getSubsystemPath(m.Cgroups, "freezer")
 | 
						path, err := getSubsystemPath(m.Cgroups, "freezer")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	prevState := m.Cgroups.Resources.Freezer
 | 
						prevState := m.Cgroups.Resources.Freezer
 | 
				
			||||||
	m.Cgroups.Resources.Freezer = state
 | 
						m.Cgroups.Resources.Freezer = state
 | 
				
			||||||
	freezer, err := subsystems.Get("freezer")
 | 
						freezer, err := legacySubsystems.Get("freezer")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -475,7 +427,7 @@ func (m *Manager) Freeze(state configs.FreezerState) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) GetPids() ([]int, error) {
 | 
					func (m *LegacyManager) GetPids() ([]int, error) {
 | 
				
			||||||
	path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
						path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -483,7 +435,7 @@ func (m *Manager) GetPids() ([]int, error) {
 | 
				
			|||||||
	return cgroups.GetPids(path)
 | 
						return cgroups.GetPids(path)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) GetAllPids() ([]int, error) {
 | 
					func (m *LegacyManager) GetAllPids() ([]int, error) {
 | 
				
			||||||
	path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
						path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -491,12 +443,12 @@ func (m *Manager) GetAllPids() ([]int, error) {
 | 
				
			|||||||
	return cgroups.GetAllPids(path)
 | 
						return cgroups.GetAllPids(path)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) GetStats() (*cgroups.Stats, error) {
 | 
					func (m *LegacyManager) GetStats() (*cgroups.Stats, error) {
 | 
				
			||||||
	m.mu.Lock()
 | 
						m.mu.Lock()
 | 
				
			||||||
	defer m.mu.Unlock()
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
	stats := cgroups.NewStats()
 | 
						stats := cgroups.NewStats()
 | 
				
			||||||
	for name, path := range m.Paths {
 | 
						for name, path := range m.Paths {
 | 
				
			||||||
		sys, err := subsystems.Get(name)
 | 
							sys, err := legacySubsystems.Get(name)
 | 
				
			||||||
		if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 | 
							if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -508,13 +460,13 @@ func (m *Manager) GetStats() (*cgroups.Stats, error) {
 | 
				
			|||||||
	return stats, nil
 | 
						return stats, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (m *Manager) Set(container *configs.Config) error {
 | 
					func (m *LegacyManager) Set(container *configs.Config) error {
 | 
				
			||||||
	// If Paths are set, then we are just joining cgroups paths
 | 
						// If Paths are set, then we are just joining cgroups paths
 | 
				
			||||||
	// and there is no need to set any values.
 | 
						// and there is no need to set any values.
 | 
				
			||||||
	if m.Cgroups.Paths != nil {
 | 
						if m.Cgroups.Paths != nil {
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, sys := range subsystems {
 | 
						for _, sys := range legacySubsystems {
 | 
				
			||||||
		// Get the subsystem path, but don't error out for not found cgroups.
 | 
							// Get the subsystem path, but don't error out for not found cgroups.
 | 
				
			||||||
		path, err := getSubsystemPath(container.Cgroups, sys.Name())
 | 
							path, err := getSubsystemPath(container.Cgroups, sys.Name())
 | 
				
			||||||
		if err != nil && !cgroups.IsNotFound(err) {
 | 
							if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										329
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/unified_hierarchy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										329
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/systemd/unified_hierarchy.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,329 @@
 | 
				
			|||||||
 | 
					// +build linux,!static_build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package systemd
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"math"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						systemdDbus "github.com/coreos/go-systemd/dbus"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups/fs"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type UnifiedManager struct {
 | 
				
			||||||
 | 
						mu      sync.Mutex
 | 
				
			||||||
 | 
						Cgroups *configs.Cgroup
 | 
				
			||||||
 | 
						Paths   map[string]string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var unifiedSubsystems = subsystemSet{
 | 
				
			||||||
 | 
						&fs.CpusetGroupV2{},
 | 
				
			||||||
 | 
						&fs.FreezerGroupV2{},
 | 
				
			||||||
 | 
						&fs.CpuGroupV2{},
 | 
				
			||||||
 | 
						&fs.MemoryGroupV2{},
 | 
				
			||||||
 | 
						&fs.IOGroupV2{},
 | 
				
			||||||
 | 
						&fs.PidsGroupV2{},
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) Apply(pid int) error {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							c          = m.Cgroups
 | 
				
			||||||
 | 
							unitName   = getUnitName(c)
 | 
				
			||||||
 | 
							slice      = "system.slice"
 | 
				
			||||||
 | 
							properties []systemdDbus.Property
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Paths != nil {
 | 
				
			||||||
 | 
							paths := make(map[string]string)
 | 
				
			||||||
 | 
							for name, path := range c.Paths {
 | 
				
			||||||
 | 
								_, err := getSubsystemPath(m.Cgroups, name)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 | 
				
			||||||
 | 
									if cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
										continue
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								paths[name] = path
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m.Paths = paths
 | 
				
			||||||
 | 
							return cgroups.EnterPid(m.Paths, pid)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Parent != "" {
 | 
				
			||||||
 | 
							slice = c.Parent
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						properties = append(properties, systemdDbus.PropDescription("libcontainer container "+c.Name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// if we create a slice, the parent is defined via a Wants=
 | 
				
			||||||
 | 
						if strings.HasSuffix(unitName, ".slice") {
 | 
				
			||||||
 | 
							properties = append(properties, systemdDbus.PropWants(slice))
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							// otherwise, we use Slice=
 | 
				
			||||||
 | 
							properties = append(properties, systemdDbus.PropSlice(slice))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// only add pid if its valid, -1 is used w/ general slice creation.
 | 
				
			||||||
 | 
						if pid != -1 {
 | 
				
			||||||
 | 
							properties = append(properties, newProp("PIDs", []uint32{uint32(pid)}))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Check if we can delegate. This is only supported on systemd versions 218 and above.
 | 
				
			||||||
 | 
						if !strings.HasSuffix(unitName, ".slice") {
 | 
				
			||||||
 | 
							// Assume scopes always support delegation.
 | 
				
			||||||
 | 
							properties = append(properties, newProp("Delegate", true))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Always enable accounting, this gets us the same behaviour as the fs implementation,
 | 
				
			||||||
 | 
						// plus the kernel has some problems with joining the memory cgroup at a later time.
 | 
				
			||||||
 | 
						properties = append(properties,
 | 
				
			||||||
 | 
							newProp("MemoryAccounting", true),
 | 
				
			||||||
 | 
							newProp("CPUAccounting", true),
 | 
				
			||||||
 | 
							newProp("BlockIOAccounting", true))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assume DefaultDependencies= will always work (the check for it was previously broken.)
 | 
				
			||||||
 | 
						properties = append(properties,
 | 
				
			||||||
 | 
							newProp("DefaultDependencies", false))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Resources.Memory != 0 {
 | 
				
			||||||
 | 
							properties = append(properties,
 | 
				
			||||||
 | 
								newProp("MemoryLimit", uint64(c.Resources.Memory)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Resources.CpuShares != 0 {
 | 
				
			||||||
 | 
							properties = append(properties,
 | 
				
			||||||
 | 
								newProp("CPUShares", c.Resources.CpuShares))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// cpu.cfs_quota_us and cpu.cfs_period_us are controlled by systemd.
 | 
				
			||||||
 | 
						if c.Resources.CpuQuota != 0 && c.Resources.CpuPeriod != 0 {
 | 
				
			||||||
 | 
							// corresponds to USEC_INFINITY in systemd
 | 
				
			||||||
 | 
							// if USEC_INFINITY is provided, CPUQuota is left unbound by systemd
 | 
				
			||||||
 | 
							// always setting a property value ensures we can apply a quota and remove it later
 | 
				
			||||||
 | 
							cpuQuotaPerSecUSec := uint64(math.MaxUint64)
 | 
				
			||||||
 | 
							if c.Resources.CpuQuota > 0 {
 | 
				
			||||||
 | 
								// systemd converts CPUQuotaPerSecUSec (microseconds per CPU second) to CPUQuota
 | 
				
			||||||
 | 
								// (integer percentage of CPU) internally.  This means that if a fractional percent of
 | 
				
			||||||
 | 
								// CPU is indicated by Resources.CpuQuota, we need to round up to the nearest
 | 
				
			||||||
 | 
								// 10ms (1% of a second) such that child cgroups can set the cpu.cfs_quota_us they expect.
 | 
				
			||||||
 | 
								cpuQuotaPerSecUSec = uint64(c.Resources.CpuQuota*1000000) / c.Resources.CpuPeriod
 | 
				
			||||||
 | 
								if cpuQuotaPerSecUSec%10000 != 0 {
 | 
				
			||||||
 | 
									cpuQuotaPerSecUSec = ((cpuQuotaPerSecUSec / 10000) + 1) * 10000
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							properties = append(properties,
 | 
				
			||||||
 | 
								newProp("CPUQuotaPerSecUSec", cpuQuotaPerSecUSec))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Resources.BlkioWeight != 0 {
 | 
				
			||||||
 | 
							properties = append(properties,
 | 
				
			||||||
 | 
								newProp("BlockIOWeight", uint64(c.Resources.BlkioWeight)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if c.Resources.PidsLimit > 0 {
 | 
				
			||||||
 | 
							properties = append(properties,
 | 
				
			||||||
 | 
								newProp("TasksAccounting", true),
 | 
				
			||||||
 | 
								newProp("TasksMax", uint64(c.Resources.PidsLimit)))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// We have to set kernel memory here, as we can't change it once
 | 
				
			||||||
 | 
						// processes have been attached to the cgroup.
 | 
				
			||||||
 | 
						if c.Resources.KernelMemory != 0 {
 | 
				
			||||||
 | 
							if err := setKernelMemory(c); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						statusChan := make(chan string, 1)
 | 
				
			||||||
 | 
						if _, err := theConn.StartTransientUnit(unitName, "replace", properties, statusChan); err == nil {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-statusChan:
 | 
				
			||||||
 | 
							case <-time.After(time.Second):
 | 
				
			||||||
 | 
								logrus.Warnf("Timed out while waiting for StartTransientUnit(%s) completion signal from dbus. Continuing...", unitName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else if !isUnitExists(err) {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := joinCgroupsV2(c, pid); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						paths := make(map[string]string)
 | 
				
			||||||
 | 
						for _, s := range unifiedSubsystems {
 | 
				
			||||||
 | 
							subsystemPath, err := getSubsystemPath(m.Cgroups, s.Name())
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								// Don't fail if a cgroup hierarchy was not found, just skip this subsystem
 | 
				
			||||||
 | 
								if cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							paths[s.Name()] = subsystemPath
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.Paths = paths
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) Destroy() error {
 | 
				
			||||||
 | 
						if m.Cgroups.Paths != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.mu.Lock()
 | 
				
			||||||
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
 | 
						theConn.StopUnit(getUnitName(m.Cgroups), "replace", nil)
 | 
				
			||||||
 | 
						if err := cgroups.RemovePaths(m.Paths); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m.Paths = make(map[string]string)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) GetPaths() map[string]string {
 | 
				
			||||||
 | 
						m.mu.Lock()
 | 
				
			||||||
 | 
						paths := m.Paths
 | 
				
			||||||
 | 
						m.mu.Unlock()
 | 
				
			||||||
 | 
						return paths
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func createCgroupsv2Path(path string) (Err error) {
 | 
				
			||||||
 | 
						content, err := ioutil.ReadFile("/sys/fs/cgroup/cgroup.controllers")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if !filepath.HasPrefix(path, "/sys/fs/cgroup") {
 | 
				
			||||||
 | 
							return fmt.Errorf("invalid cgroup path %s", path)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						res := ""
 | 
				
			||||||
 | 
						for i, c := range strings.Split(strings.TrimSpace(string(content)), " ") {
 | 
				
			||||||
 | 
							if i == 0 {
 | 
				
			||||||
 | 
								res = fmt.Sprintf("+%s", c)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								res = res + fmt.Sprintf(" +%s", c)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resByte := []byte(res)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						current := "/sys/fs"
 | 
				
			||||||
 | 
						elements := strings.Split(path, "/")
 | 
				
			||||||
 | 
						for i, e := range elements[3:] {
 | 
				
			||||||
 | 
							current = filepath.Join(current, e)
 | 
				
			||||||
 | 
							if i > 0 {
 | 
				
			||||||
 | 
								if err := os.Mkdir(current, 0755); err != nil {
 | 
				
			||||||
 | 
									if !os.IsExist(err) {
 | 
				
			||||||
 | 
										return err
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									// If the directory was created, be sure it is not left around on errors.
 | 
				
			||||||
 | 
									defer func() {
 | 
				
			||||||
 | 
										if Err != nil {
 | 
				
			||||||
 | 
											os.Remove(current)
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}()
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if i < len(elements[3:])-1 {
 | 
				
			||||||
 | 
								if err := ioutil.WriteFile(filepath.Join(current, "cgroup.subtree_control"), resByte, 0755); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func joinCgroupsV2(c *configs.Cgroup, pid int) error {
 | 
				
			||||||
 | 
						path, err := getSubsystemPath(c, "memory")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return createCgroupsv2Path(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) Freeze(state configs.FreezerState) error {
 | 
				
			||||||
 | 
						path, err := getSubsystemPath(m.Cgroups, "freezer")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						prevState := m.Cgroups.Resources.Freezer
 | 
				
			||||||
 | 
						m.Cgroups.Resources.Freezer = state
 | 
				
			||||||
 | 
						freezer, err := unifiedSubsystems.Get("freezer")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						err = freezer.Set(path, m.Cgroups)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							m.Cgroups.Resources.Freezer = prevState
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) GetPids() ([]int, error) {
 | 
				
			||||||
 | 
						path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cgroups.GetPids(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) GetAllPids() ([]int, error) {
 | 
				
			||||||
 | 
						path, err := getSubsystemPath(m.Cgroups, "devices")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return cgroups.GetAllPids(path)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) GetStats() (*cgroups.Stats, error) {
 | 
				
			||||||
 | 
						m.mu.Lock()
 | 
				
			||||||
 | 
						defer m.mu.Unlock()
 | 
				
			||||||
 | 
						stats := cgroups.NewStats()
 | 
				
			||||||
 | 
						for name, path := range m.Paths {
 | 
				
			||||||
 | 
							sys, err := unifiedSubsystems.Get(name)
 | 
				
			||||||
 | 
							if err == errSubsystemDoesNotExist || !cgroups.PathExists(path) {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if err := sys.GetStats(path, stats); err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stats, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (m *UnifiedManager) Set(container *configs.Config) error {
 | 
				
			||||||
 | 
						// If Paths are set, then we are just joining cgroups paths
 | 
				
			||||||
 | 
						// and there is no need to set any values.
 | 
				
			||||||
 | 
						if m.Cgroups.Paths != nil {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, sys := range unifiedSubsystems {
 | 
				
			||||||
 | 
							// Get the subsystem path, but don't error out for not found cgroups.
 | 
				
			||||||
 | 
							path, err := getSubsystemPath(container.Cgroups, sys.Name())
 | 
				
			||||||
 | 
							if err != nil && !cgroups.IsNotFound(err) {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := sys.Set(path, container.Cgroups); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if m.Paths["cpu"] != "" {
 | 
				
			||||||
 | 
							if err := fs.CheckCpushares(m.Paths["cpu"], container.Cgroups.Resources.CpuShares); err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										58
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										58
									
								
								vendor/github.com/opencontainers/runc/libcontainer/cgroups/utils.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -11,6 +11,8 @@ import (
 | 
				
			|||||||
	"path/filepath"
 | 
						"path/filepath"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
 | 
						"syscall"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	units "github.com/docker/go-units"
 | 
						units "github.com/docker/go-units"
 | 
				
			||||||
@@ -22,6 +24,11 @@ const (
 | 
				
			|||||||
	CgroupProcesses  = "cgroup.procs"
 | 
						CgroupProcesses  = "cgroup.procs"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						isUnifiedOnce sync.Once
 | 
				
			||||||
 | 
						isUnified     bool
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// HugePageSizeUnitList is a list of the units used by the linux kernel when
 | 
					// HugePageSizeUnitList is a list of the units used by the linux kernel when
 | 
				
			||||||
// naming the HugePage control files.
 | 
					// naming the HugePage control files.
 | 
				
			||||||
// https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt
 | 
					// https://www.kernel.org/doc/Documentation/cgroup-v1/hugetlb.txt
 | 
				
			||||||
@@ -29,6 +36,18 @@ const (
 | 
				
			|||||||
// depends on https://github.com/docker/go-units/commit/a09cd47f892041a4fac473133d181f5aea6fa393
 | 
					// depends on https://github.com/docker/go-units/commit/a09cd47f892041a4fac473133d181f5aea6fa393
 | 
				
			||||||
var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
 | 
					var HugePageSizeUnitList = []string{"B", "KB", "MB", "GB", "TB", "PB"}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// IsCgroup2UnifiedMode returns whether we are running in cgroup v2 unified mode.
 | 
				
			||||||
 | 
					func IsCgroup2UnifiedMode() bool {
 | 
				
			||||||
 | 
						isUnifiedOnce.Do(func() {
 | 
				
			||||||
 | 
							var st syscall.Statfs_t
 | 
				
			||||||
 | 
							if err := syscall.Statfs("/sys/fs/cgroup", &st); err != nil {
 | 
				
			||||||
 | 
								panic("cannot statfs cgroup root")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							isUnified = st.Type == unix.CGROUP2_SUPER_MAGIC
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						return isUnified
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
 | 
					// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
 | 
				
			||||||
func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
 | 
					func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) {
 | 
				
			||||||
	mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
 | 
						mnt, _, err := FindCgroupMountpointAndRoot(cgroupPath, subsystem)
 | 
				
			||||||
@@ -49,6 +68,10 @@ func FindCgroupMountpointAndRoot(cgroupPath, subsystem string) (string, string,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	defer f.Close()
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							subsystem = ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return findCgroupMountpointAndRootFromReader(f, cgroupPath, subsystem)
 | 
						return findCgroupMountpointAndRootFromReader(f, cgroupPath, subsystem)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,12 +80,12 @@ func findCgroupMountpointAndRootFromReader(reader io.Reader, cgroupPath, subsyst
 | 
				
			|||||||
	for scanner.Scan() {
 | 
						for scanner.Scan() {
 | 
				
			||||||
		txt := scanner.Text()
 | 
							txt := scanner.Text()
 | 
				
			||||||
		fields := strings.Fields(txt)
 | 
							fields := strings.Fields(txt)
 | 
				
			||||||
		if len(fields) < 5 {
 | 
							if len(fields) < 9 {
 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if strings.HasPrefix(fields[4], cgroupPath) {
 | 
							if strings.HasPrefix(fields[4], cgroupPath) {
 | 
				
			||||||
			for _, opt := range strings.Split(fields[len(fields)-1], ",") {
 | 
								for _, opt := range strings.Split(fields[len(fields)-1], ",") {
 | 
				
			||||||
				if opt == subsystem {
 | 
									if (subsystem == "" && fields[9] == "cgroup2") || opt == subsystem {
 | 
				
			||||||
					return fields[4], fields[3], nil
 | 
										return fields[4], fields[3], nil
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -76,6 +99,19 @@ func findCgroupMountpointAndRootFromReader(reader io.Reader, cgroupPath, subsyst
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func isSubsystemAvailable(subsystem string) bool {
 | 
					func isSubsystemAvailable(subsystem string) bool {
 | 
				
			||||||
 | 
						if IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							controllers, err := GetAllSubsystems()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							for _, c := range controllers {
 | 
				
			||||||
 | 
								if c == subsystem {
 | 
				
			||||||
 | 
									return true
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cgroups, err := ParseCgroupFile("/proc/self/cgroup")
 | 
						cgroups, err := ParseCgroupFile("/proc/self/cgroup")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
@@ -120,7 +156,7 @@ func FindCgroupMountpointDir() (string, error) {
 | 
				
			|||||||
			return "", fmt.Errorf("Found no fields post '-' in %q", text)
 | 
								return "", fmt.Errorf("Found no fields post '-' in %q", text)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if postSeparatorFields[0] == "cgroup" {
 | 
							if postSeparatorFields[0] == "cgroup" || postSeparatorFields[0] == "cgroup2" {
 | 
				
			||||||
			// Check that the mount is properly formatted.
 | 
								// Check that the mount is properly formatted.
 | 
				
			||||||
			if numPostFields < 3 {
 | 
								if numPostFields < 3 {
 | 
				
			||||||
				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
 | 
									return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
 | 
				
			||||||
@@ -193,6 +229,19 @@ func getCgroupMountsHelper(ss map[string]bool, mi io.Reader, all bool) ([]Mount,
 | 
				
			|||||||
// GetCgroupMounts returns the mounts for the cgroup subsystems.
 | 
					// GetCgroupMounts returns the mounts for the cgroup subsystems.
 | 
				
			||||||
// all indicates whether to return just the first instance or all the mounts.
 | 
					// all indicates whether to return just the first instance or all the mounts.
 | 
				
			||||||
func GetCgroupMounts(all bool) ([]Mount, error) {
 | 
					func GetCgroupMounts(all bool) ([]Mount, error) {
 | 
				
			||||||
 | 
						if IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							availableControllers, err := GetAllSubsystems()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							m := Mount{
 | 
				
			||||||
 | 
								Mountpoint: "/sys/fs/cgroup",
 | 
				
			||||||
 | 
								Root:       "/sys/fs/cgroup",
 | 
				
			||||||
 | 
								Subsystems: availableControllers,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return []Mount{m}, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	f, err := os.Open("/proc/self/mountinfo")
 | 
						f, err := os.Open("/proc/self/mountinfo")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@@ -356,6 +405,9 @@ func parseCgroupFromReader(r io.Reader) (map[string]string, error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {
 | 
					func getControllerPath(subsystem string, cgroups map[string]string) (string, error) {
 | 
				
			||||||
 | 
						if IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							return "/", nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if p, ok := cgroups[subsystem]; ok {
 | 
						if p, ok := cgroups[subsystem]; ok {
 | 
				
			||||||
		return p, nil
 | 
							return p, nil
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/BUILD
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -5,7 +5,7 @@ go_library(
 | 
				
			|||||||
    srcs = [
 | 
					    srcs = [
 | 
				
			||||||
        "blkio_device.go",
 | 
					        "blkio_device.go",
 | 
				
			||||||
        "cgroup_linux.go",
 | 
					        "cgroup_linux.go",
 | 
				
			||||||
        "cgroup_windows.go",
 | 
					        "cgroup_unsupported.go",
 | 
				
			||||||
        "config.go",
 | 
					        "config.go",
 | 
				
			||||||
        "config_linux.go",
 | 
					        "config_linux.go",
 | 
				
			||||||
        "device.go",
 | 
					        "device.go",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/blkio_device.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/blkio_device.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -59,3 +59,8 @@ func NewThrottleDevice(major, minor int64, rate uint64) *ThrottleDevice {
 | 
				
			|||||||
func (td *ThrottleDevice) String() string {
 | 
					func (td *ThrottleDevice) String() string {
 | 
				
			||||||
	return fmt.Sprintf("%d:%d %d", td.Major, td.Minor, td.Rate)
 | 
						return fmt.Sprintf("%d:%d %d", td.Major, td.Minor, td.Rate)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// StringName formats the struct to be writable to the cgroup specific file
 | 
				
			||||||
 | 
					func (td *ThrottleDevice) StringName(name string) string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("%d:%d %s=%d", td.Major, td.Minor, name, td.Rate)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/cgroup_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -119,4 +119,12 @@ type Resources struct {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Set class identifier for container's network packets
 | 
						// Set class identifier for container's network packets
 | 
				
			||||||
	NetClsClassid uint32 `json:"net_cls_classid_u"`
 | 
						NetClsClassid uint32 `json:"net_cls_classid_u"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Used on cgroups v2:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CpuWeight sets a proportional bandwidth limit.
 | 
				
			||||||
 | 
						CpuWeight uint64 `json:"cpu_weight"`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// CpuMax sets she maximum bandwidth limit (format: max period).
 | 
				
			||||||
 | 
						CpuMax string `json:"cpu_max"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					// +build !linux
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package configs
 | 
					package configs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO Windows: This can ultimately be entirely factored out on Windows as
 | 
					// TODO Windows: This can ultimately be entirely factored out on Windows as
 | 
				
			||||||
							
								
								
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/configs/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -44,6 +44,7 @@ const (
 | 
				
			|||||||
	Trap
 | 
						Trap
 | 
				
			||||||
	Allow
 | 
						Allow
 | 
				
			||||||
	Trace
 | 
						Trace
 | 
				
			||||||
 | 
						Log
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
 | 
					// Operator is a comparison operator to be used when matching syscall arguments in Seccomp
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										15
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/opencontainers/runc/libcontainer/container_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,7 +19,7 @@ import (
 | 
				
			|||||||
	"syscall" // only for SysProcAttr and Signal
 | 
						"syscall" // only for SysProcAttr and Signal
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/cyphar/filepath-securejoin"
 | 
						securejoin "github.com/cyphar/filepath-securejoin"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/configs"
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/intelrdt"
 | 
						"github.com/opencontainers/runc/libcontainer/intelrdt"
 | 
				
			||||||
@@ -1176,7 +1176,7 @@ func (c *linuxContainer) makeCriuRestoreMountpoints(m *configs.Mount) error {
 | 
				
			|||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := checkMountDestination(c.config.Rootfs, dest); err != nil {
 | 
							if err := checkProcMount(c.config.Rootfs, dest, ""); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		m.Destination = dest
 | 
							m.Destination = dest
 | 
				
			||||||
@@ -1814,7 +1814,14 @@ func (c *linuxContainer) isPaused() (bool, error) {
 | 
				
			|||||||
		// A container doesn't have a freezer cgroup
 | 
							// A container doesn't have a freezer cgroup
 | 
				
			||||||
		return false, nil
 | 
							return false, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	data, err := ioutil.ReadFile(filepath.Join(fcg, "freezer.state"))
 | 
						pausedState := "FROZEN"
 | 
				
			||||||
 | 
						filename := "freezer.state"
 | 
				
			||||||
 | 
						if cgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
 | 
							filename = "cgroup.freeze"
 | 
				
			||||||
 | 
							pausedState = "1"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, err := ioutil.ReadFile(filepath.Join(fcg, filename))
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		// If freezer cgroup is not mounted, the container would just be not paused.
 | 
							// If freezer cgroup is not mounted, the container would just be not paused.
 | 
				
			||||||
		if os.IsNotExist(err) {
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
@@ -1822,7 +1829,7 @@ func (c *linuxContainer) isPaused() (bool, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		return false, newSystemErrorWithCause(err, "checking if container is paused")
 | 
							return false, newSystemErrorWithCause(err, "checking if container is paused")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return bytes.Equal(bytes.TrimSpace(data), []byte("FROZEN")), nil
 | 
						return bytes.Equal(bytes.TrimSpace(data), []byte(pausedState)), nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (c *linuxContainer) currentState() (*State, error) {
 | 
					func (c *linuxContainer) currentState() (*State, error) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										182
									
								
								vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										182
									
								
								vendor/github.com/opencontainers/runc/libcontainer/rootfs_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -13,7 +13,7 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/cyphar/filepath-securejoin"
 | 
						securejoin "github.com/cyphar/filepath-securejoin"
 | 
				
			||||||
	"github.com/mrunalp/fileutils"
 | 
						"github.com/mrunalp/fileutils"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	"github.com/opencontainers/runc/libcontainer/configs"
 | 
						"github.com/opencontainers/runc/libcontainer/configs"
 | 
				
			||||||
@@ -197,7 +197,7 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
 | 
				
			|||||||
	if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
 | 
						if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if err := checkMountDestination(rootfs, dest); err != nil {
 | 
						if err := checkProcMount(rootfs, dest, m.Source); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// update the mount with the correct dest after symlinks are resolved.
 | 
						// update the mount with the correct dest after symlinks are resolved.
 | 
				
			||||||
@@ -209,6 +209,80 @@ func prepareBindMount(m *configs.Mount, rootfs string) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mountCgroupV1(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
 | 
				
			||||||
 | 
						binds, err := getCgroupMounts(m)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						var merged []string
 | 
				
			||||||
 | 
						for _, b := range binds {
 | 
				
			||||||
 | 
							ss := filepath.Base(b.Destination)
 | 
				
			||||||
 | 
							if strings.Contains(ss, ",") {
 | 
				
			||||||
 | 
								merged = append(merged, ss)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tmpfs := &configs.Mount{
 | 
				
			||||||
 | 
							Source:           "tmpfs",
 | 
				
			||||||
 | 
							Device:           "tmpfs",
 | 
				
			||||||
 | 
							Destination:      m.Destination,
 | 
				
			||||||
 | 
							Flags:            defaultMountFlags,
 | 
				
			||||||
 | 
							Data:             "mode=755",
 | 
				
			||||||
 | 
							PropagationFlags: m.PropagationFlags,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := mountToRootfs(tmpfs, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, b := range binds {
 | 
				
			||||||
 | 
							if enableCgroupns {
 | 
				
			||||||
 | 
								subsystemPath := filepath.Join(rootfs, b.Destination)
 | 
				
			||||||
 | 
								if err := os.MkdirAll(subsystemPath, 0755); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								flags := defaultMountFlags
 | 
				
			||||||
 | 
								if m.Flags&unix.MS_RDONLY != 0 {
 | 
				
			||||||
 | 
									flags = flags | unix.MS_RDONLY
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								cgroupmount := &configs.Mount{
 | 
				
			||||||
 | 
									Source:      "cgroup",
 | 
				
			||||||
 | 
									Device:      "cgroup",
 | 
				
			||||||
 | 
									Destination: subsystemPath,
 | 
				
			||||||
 | 
									Flags:       flags,
 | 
				
			||||||
 | 
									Data:        filepath.Base(subsystemPath),
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if err := mountNewCgroup(cgroupmount); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if err := mountToRootfs(b, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, mc := range merged {
 | 
				
			||||||
 | 
							for _, ss := range strings.Split(mc, ",") {
 | 
				
			||||||
 | 
								// symlink(2) is very dumb, it will just shove the path into
 | 
				
			||||||
 | 
								// the link and doesn't do any checks or relative path
 | 
				
			||||||
 | 
								// conversion. Also, don't error out if the cgroup already exists.
 | 
				
			||||||
 | 
								if err := os.Symlink(mc, filepath.Join(rootfs, m.Destination, ss)); err != nil && !os.IsExist(err) {
 | 
				
			||||||
 | 
									return err
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func mountCgroupV2(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
 | 
				
			||||||
 | 
						cgroupPath, err := securejoin.SecureJoin(rootfs, m.Destination)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := os.MkdirAll(cgroupPath, 0755); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return unix.Mount(m.Source, cgroupPath, "cgroup2", uintptr(m.Flags), m.Data)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
 | 
					func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns bool) error {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		dest = m.Destination
 | 
							dest = m.Destination
 | 
				
			||||||
@@ -309,64 +383,16 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	case "cgroup":
 | 
						case "cgroup":
 | 
				
			||||||
		binds, err := getCgroupMounts(m)
 | 
							if cgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
		if err != nil {
 | 
								if err := mountCgroupV2(m, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		var merged []string
 | 
					 | 
				
			||||||
		for _, b := range binds {
 | 
					 | 
				
			||||||
			ss := filepath.Base(b.Destination)
 | 
					 | 
				
			||||||
			if strings.Contains(ss, ",") {
 | 
					 | 
				
			||||||
				merged = append(merged, ss)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		tmpfs := &configs.Mount{
 | 
					 | 
				
			||||||
			Source:           "tmpfs",
 | 
					 | 
				
			||||||
			Device:           "tmpfs",
 | 
					 | 
				
			||||||
			Destination:      m.Destination,
 | 
					 | 
				
			||||||
			Flags:            defaultMountFlags,
 | 
					 | 
				
			||||||
			Data:             "mode=755",
 | 
					 | 
				
			||||||
			PropagationFlags: m.PropagationFlags,
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err := mountToRootfs(tmpfs, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, b := range binds {
 | 
					 | 
				
			||||||
			if enableCgroupns {
 | 
					 | 
				
			||||||
				subsystemPath := filepath.Join(rootfs, b.Destination)
 | 
					 | 
				
			||||||
				if err := os.MkdirAll(subsystemPath, 0755); err != nil {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				flags := defaultMountFlags
 | 
					 | 
				
			||||||
				if m.Flags&unix.MS_RDONLY != 0 {
 | 
					 | 
				
			||||||
					flags = flags | unix.MS_RDONLY
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				cgroupmount := &configs.Mount{
 | 
					 | 
				
			||||||
					Source:      "cgroup",
 | 
					 | 
				
			||||||
					Device:      "cgroup",
 | 
					 | 
				
			||||||
					Destination: subsystemPath,
 | 
					 | 
				
			||||||
					Flags:       flags,
 | 
					 | 
				
			||||||
					Data:        filepath.Base(subsystemPath),
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if err := mountNewCgroup(cgroupmount); err != nil {
 | 
					 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
				if err := mountToRootfs(b, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
					
 | 
				
			||||||
 | 
								if err := mountCgroupV1(m, rootfs, mountLabel, enableCgroupns); err != nil {
 | 
				
			||||||
				return err
 | 
									return err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		for _, mc := range merged {
 | 
					 | 
				
			||||||
			for _, ss := range strings.Split(mc, ",") {
 | 
					 | 
				
			||||||
				// symlink(2) is very dumb, it will just shove the path into
 | 
					 | 
				
			||||||
				// the link and doesn't do any checks or relative path
 | 
					 | 
				
			||||||
				// conversion. Also, don't error out if the cgroup already exists.
 | 
					 | 
				
			||||||
				if err := os.Symlink(mc, filepath.Join(rootfs, m.Destination, ss)); err != nil && !os.IsExist(err) {
 | 
					 | 
				
			||||||
					return err
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if m.Flags&unix.MS_RDONLY != 0 {
 | 
							if m.Flags&unix.MS_RDONLY != 0 {
 | 
				
			||||||
			// remount cgroup root as readonly
 | 
								// remount cgroup root as readonly
 | 
				
			||||||
			mcgrouproot := &configs.Mount{
 | 
								mcgrouproot := &configs.Mount{
 | 
				
			||||||
@@ -388,7 +414,7 @@ func mountToRootfs(m *configs.Mount, rootfs, mountLabel string, enableCgroupns b
 | 
				
			|||||||
		if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
 | 
							if dest, err = securejoin.SecureJoin(rootfs, m.Destination); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := checkMountDestination(rootfs, dest); err != nil {
 | 
							if err := checkProcMount(rootfs, dest, m.Source); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// update the mount with the correct dest after symlinks are resolved.
 | 
							// update the mount with the correct dest after symlinks are resolved.
 | 
				
			||||||
@@ -435,12 +461,12 @@ func getCgroupMounts(m *configs.Mount) ([]*configs.Mount, error) {
 | 
				
			|||||||
	return binds, nil
 | 
						return binds, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// checkMountDestination checks to ensure that the mount destination is not over the top of /proc.
 | 
					// checkProcMount checks to ensure that the mount destination is not over the top of /proc.
 | 
				
			||||||
// dest is required to be an abs path and have any symlinks resolved before calling this function.
 | 
					// dest is required to be an abs path and have any symlinks resolved before calling this function.
 | 
				
			||||||
func checkMountDestination(rootfs, dest string) error {
 | 
					//
 | 
				
			||||||
	invalidDestinations := []string{
 | 
					// if source is nil, don't stat the filesystem.  This is used for restore of a checkpoint.
 | 
				
			||||||
		"/proc",
 | 
					func checkProcMount(rootfs, dest, source string) error {
 | 
				
			||||||
	}
 | 
						const procPath = "/proc"
 | 
				
			||||||
	// White list, it should be sub directories of invalid destinations
 | 
						// White list, it should be sub directories of invalid destinations
 | 
				
			||||||
	validDestinations := []string{
 | 
						validDestinations := []string{
 | 
				
			||||||
		// These entries can be bind mounted by files emulated by fuse,
 | 
							// These entries can be bind mounted by files emulated by fuse,
 | 
				
			||||||
@@ -463,16 +489,40 @@ func checkMountDestination(rootfs, dest string) error {
 | 
				
			|||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, invalid := range invalidDestinations {
 | 
						path, err := filepath.Rel(filepath.Join(rootfs, procPath), dest)
 | 
				
			||||||
		path, err := filepath.Rel(filepath.Join(rootfs, invalid), dest)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		if path != "." && !strings.HasPrefix(path, "..") {
 | 
						// pass if the mount path is located outside of /proc
 | 
				
			||||||
			return fmt.Errorf("%q cannot be mounted because it is located inside %q", dest, invalid)
 | 
						if strings.HasPrefix(path, "..") {
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if path == "." {
 | 
				
			||||||
 | 
							// an empty source is pasted on restore
 | 
				
			||||||
 | 
							if source == "" {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// only allow a mount on-top of proc if it's source is "proc"
 | 
				
			||||||
 | 
							isproc, err := isProc(source)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							// pass if the mount is happening on top of /proc and the source of
 | 
				
			||||||
 | 
							// the mount is a proc filesystem
 | 
				
			||||||
 | 
							if isproc {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return fmt.Errorf("%q cannot be mounted because it is not of type proc", dest)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return fmt.Errorf("%q cannot be mounted because it is inside /proc", dest)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func isProc(path string) (bool, error) {
 | 
				
			||||||
 | 
						var s unix.Statfs_t
 | 
				
			||||||
 | 
						if err := unix.Statfs(path, &s); err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s.Type == unix.PROC_SUPER_MAGIC, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func setupDevSymlinks(rootfs string) error {
 | 
					func setupDevSymlinks(rootfs string) error {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/config.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -22,6 +22,7 @@ var actions = map[string]configs.Action{
 | 
				
			|||||||
	"SCMP_ACT_TRAP":  configs.Trap,
 | 
						"SCMP_ACT_TRAP":  configs.Trap,
 | 
				
			||||||
	"SCMP_ACT_ALLOW": configs.Allow,
 | 
						"SCMP_ACT_ALLOW": configs.Allow,
 | 
				
			||||||
	"SCMP_ACT_TRACE": configs.Trace,
 | 
						"SCMP_ACT_TRACE": configs.Trace,
 | 
				
			||||||
 | 
						"SCMP_ACT_LOG":   configs.Log,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var archs = map[string]string{
 | 
					var archs = map[string]string{
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/opencontainers/runc/libcontainer/seccomp/seccomp_linux.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,6 +19,7 @@ var (
 | 
				
			|||||||
	actTrap  = libseccomp.ActTrap
 | 
						actTrap  = libseccomp.ActTrap
 | 
				
			||||||
	actKill  = libseccomp.ActKill
 | 
						actKill  = libseccomp.ActKill
 | 
				
			||||||
	actTrace = libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM))
 | 
						actTrace = libseccomp.ActTrace.SetReturnCode(int16(unix.EPERM))
 | 
				
			||||||
 | 
						actLog   = libseccomp.ActLog
 | 
				
			||||||
	actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM))
 | 
						actErrno = libseccomp.ActErrno.SetReturnCode(int16(unix.EPERM))
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -112,6 +113,8 @@ func getAction(act configs.Action) (libseccomp.ScmpAction, error) {
 | 
				
			|||||||
		return actAllow, nil
 | 
							return actAllow, nil
 | 
				
			||||||
	case configs.Trace:
 | 
						case configs.Trace:
 | 
				
			||||||
		return actTrace, nil
 | 
							return actTrace, nil
 | 
				
			||||||
 | 
						case configs.Log:
 | 
				
			||||||
 | 
							return actLog, nil
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return libseccomp.ActInvalid, fmt.Errorf("invalid action, cannot use in rule")
 | 
							return libseccomp.ActInvalid, fmt.Errorf("invalid action, cannot use in rule")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/opencontainers/runc/libcontainer/system/syscall_linux_64.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
// +build linux
 | 
					// +build linux
 | 
				
			||||||
// +build arm64 amd64 mips mipsle mips64 mips64le ppc ppc64 ppc64le s390x
 | 
					// +build arm64 amd64 mips mipsle mips64 mips64le ppc ppc64 ppc64le riscv64 s390x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package system
 | 
					package system
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										44
									
								
								vendor/github.com/opencontainers/runc/libcontainer/utils/utils_unix.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -3,33 +3,57 @@
 | 
				
			|||||||
package utils
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"io/ioutil"
 | 
						"fmt"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"golang.org/x/sys/unix"
 | 
						"golang.org/x/sys/unix"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// EnsureProcHandle returns whether or not the given file handle is on procfs.
 | 
				
			||||||
 | 
					func EnsureProcHandle(fh *os.File) error {
 | 
				
			||||||
 | 
						var buf unix.Statfs_t
 | 
				
			||||||
 | 
						if err := unix.Fstatfs(int(fh.Fd()), &buf); err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("ensure %s is on procfs: %v", fh.Name(), err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if buf.Type != unix.PROC_SUPER_MAGIC {
 | 
				
			||||||
 | 
							return fmt.Errorf("%s is not on procfs", fh.Name())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// CloseExecFrom applies O_CLOEXEC to all file descriptors currently open for
 | 
				
			||||||
 | 
					// the process (except for those below the given fd value).
 | 
				
			||||||
func CloseExecFrom(minFd int) error {
 | 
					func CloseExecFrom(minFd int) error {
 | 
				
			||||||
	fdList, err := ioutil.ReadDir("/proc/self/fd")
 | 
						fdDir, err := os.Open("/proc/self/fd")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, fi := range fdList {
 | 
						defer fdDir.Close()
 | 
				
			||||||
		fd, err := strconv.Atoi(fi.Name())
 | 
					
 | 
				
			||||||
 | 
						if err := EnsureProcHandle(fdDir); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fdList, err := fdDir.Readdirnames(-1)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, fdStr := range fdList {
 | 
				
			||||||
 | 
							fd, err := strconv.Atoi(fdStr)
 | 
				
			||||||
 | 
							// Ignore non-numeric file names.
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			// ignore non-numeric file names
 | 
					 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// Ignore descriptors lower than our specified minimum.
 | 
				
			||||||
		if fd < minFd {
 | 
							if fd < minFd {
 | 
				
			||||||
			// ignore descriptors lower than our specified minimum
 | 
					 | 
				
			||||||
			continue
 | 
								continue
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
							// Intentionally ignore errors from unix.CloseOnExec -- the cases where
 | 
				
			||||||
		// intentionally ignore errors from unix.CloseOnExec
 | 
							// this might fail are basically file descriptors that have already
 | 
				
			||||||
 | 
							// been closed (including and especially the one that was created when
 | 
				
			||||||
 | 
							// ioutil.ReadDir did the "opendir" syscall).
 | 
				
			||||||
		unix.CloseOnExec(fd)
 | 
							unix.CloseOnExec(fd)
 | 
				
			||||||
		// the cases where this might fail are basically file descriptors that have already been closed (including and especially the one that was created when ioutil.ReadDir did the "opendir" syscall)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -679,7 +679,7 @@ github.com/opencontainers/go-digest
 | 
				
			|||||||
# github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1
 | 
					# github.com/opencontainers/image-spec v1.0.1 => github.com/opencontainers/image-spec v1.0.1
 | 
				
			||||||
github.com/opencontainers/image-spec/specs-go
 | 
					github.com/opencontainers/image-spec/specs-go
 | 
				
			||||||
github.com/opencontainers/image-spec/specs-go/v1
 | 
					github.com/opencontainers/image-spec/specs-go/v1
 | 
				
			||||||
# github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830 => github.com/opencontainers/runc v1.0.0-rc2.0.20190611121236-6cc515888830
 | 
					# github.com/opencontainers/runc v1.0.0-rc9 => github.com/opencontainers/runc v1.0.0-rc9
 | 
				
			||||||
github.com/opencontainers/runc/libcontainer
 | 
					github.com/opencontainers/runc/libcontainer
 | 
				
			||||||
github.com/opencontainers/runc/libcontainer/apparmor
 | 
					github.com/opencontainers/runc/libcontainer/apparmor
 | 
				
			||||||
github.com/opencontainers/runc/libcontainer/cgroups
 | 
					github.com/opencontainers/runc/libcontainer/cgroups
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user