diff --git a/checkpoint.go b/checkpoint.go index 32a62a8bcb2..556b19cd6e9 100644 --- a/checkpoint.go +++ b/checkpoint.go @@ -8,7 +8,7 @@ import ( "path/filepath" "strconv" - criu "github.com/checkpoint-restore/go-criu/v5/rpc" + criurpc "github.com/checkpoint-restore/go-criu/v5/rpc" "github.com/opencontainers/runc/libcontainer" "github.com/opencontainers/runc/libcontainer/userns" "github.com/opencontainers/runtime-spec/specs-go" @@ -133,11 +133,11 @@ func setManageCgroupsMode(context *cli.Context, options *libcontainer.CriuOpts) if cgOpt := context.String("manage-cgroups-mode"); cgOpt != "" { switch cgOpt { case "soft": - options.ManageCgroupsMode = criu.CriuCgMode_SOFT + options.ManageCgroupsMode = criurpc.CriuCgMode_SOFT case "full": - options.ManageCgroupsMode = criu.CriuCgMode_FULL + options.ManageCgroupsMode = criurpc.CriuCgMode_FULL case "strict": - options.ManageCgroupsMode = criu.CriuCgMode_STRICT + options.ManageCgroupsMode = criurpc.CriuCgMode_STRICT default: fatal(errors.New("Invalid manage cgroups mode")) } diff --git a/create.go b/create.go index 97854b846cb..e3510f6f94c 100644 --- a/create.go +++ b/create.go @@ -56,7 +56,7 @@ command(s) that get executed on start, edit the args parameter of the spec. See if err := checkArgs(context, 1, exactArgs); err != nil { return err } - status, err := startContainer(context, CT_ACT_CREATE, nil) + status, err := startContainer(context, actCreate, nil) if err == nil { // exit with the container's exit status so any external supervisor // is notified of the exit with the correct exit status. diff --git a/exec.go b/exec.go index 18c6bffdeb7..fa9a2b1b49c 100644 --- a/exec.go +++ b/exec.go @@ -180,7 +180,7 @@ func execProcess(context *cli.Context) (int, error) { consoleSocket: context.String("console-socket"), detach: context.Bool("detach"), pidFile: context.String("pid-file"), - action: CT_ACT_RUN, + action: actRun, init: false, preserveFDs: context.Int("preserve-fds"), subCgroupPaths: cgPaths, diff --git a/libcontainer/capabilities/capabilities.go b/libcontainer/capabilities/capabilities.go index d38b8a7cd89..7a63d88c366 100644 --- a/libcontainer/capabilities/capabilities.go +++ b/libcontainer/capabilities/capabilities.go @@ -113,7 +113,7 @@ func (c *Caps) ApplyBoundingSet() error { return c.pid.Apply(capability.BOUNDING) } -// Apply sets all the capabilities for the current process in the config. +// ApplyCaps sets all the capabilities for the current process in the config. func (c *Caps) ApplyCaps() error { c.pid.Clear(allCapabilityTypes) for _, g := range capTypes { diff --git a/libcontainer/cgroups/devices/devices_emulator.go b/libcontainer/cgroups/devices/devices_emulator.go index 6c61ee4c033..e1b811a4374 100644 --- a/libcontainer/cgroups/devices/devices_emulator.go +++ b/libcontainer/cgroups/devices/devices_emulator.go @@ -304,7 +304,7 @@ func EmulatorFromList(list io.Reader) (*Emulator, error) { // This function is the sole reason for all of Emulator -- to allow us // to figure out how to update a containers' cgroups without causing spurious // device errors (if possible). -func (source *Emulator) Transition(target *Emulator) ([]*devices.Rule, error) { +func (source *Emulator) Transition(target *Emulator) ([]*devices.Rule, error) { //nolint:revive // ignore receiver name should be consistent var transitionRules []*devices.Rule oldRules := source.rules diff --git a/libcontainer/cgroups/ebpf/ebpf_linux.go b/libcontainer/cgroups/ebpf/ebpf_linux.go index 104c74a890f..bcc719b6a0e 100644 --- a/libcontainer/cgroups/ebpf/ebpf_linux.go +++ b/libcontainer/cgroups/ebpf/ebpf_linux.go @@ -33,12 +33,12 @@ func findAttachedCgroupDeviceFilters(dirFd int) ([]*ebpf.Program, error) { size := 64 retries := 0 for retries < 10 { - progIds := make([]uint32, size) + progIDs := make([]uint32, size) query := bpfAttrQuery{ TargetFd: uint32(dirFd), AttachType: uint32(unix.BPF_CGROUP_DEVICE), - ProgIds: uint64(uintptr(unsafe.Pointer(&progIds[0]))), - ProgCnt: uint32(len(progIds)), + ProgIds: uint64(uintptr(unsafe.Pointer(&progIDs[0]))), + ProgCnt: uint32(len(progIDs)), } // Fetch the list of program ids. @@ -58,10 +58,10 @@ func findAttachedCgroupDeviceFilters(dirFd int) ([]*ebpf.Program, error) { } // Convert the ids to program handles. - progIds = progIds[:size] - programs := make([]*ebpf.Program, 0, len(progIds)) - for _, progId := range progIds { - program, err := ebpf.NewProgramFromID(ebpf.ProgramID(progId)) + progIDs = progIDs[:size] + programs := make([]*ebpf.Program, 0, len(progIDs)) + for _, progID := range progIDs { + program, err := ebpf.NewProgramFromID(ebpf.ProgramID(progID)) if err != nil { // We skip over programs that give us -EACCES or -EPERM. This // is necessary because there may be BPF programs that have @@ -73,14 +73,14 @@ func findAttachedCgroupDeviceFilters(dirFd int) ([]*ebpf.Program, error) { // programs (and stops runc from breaking on distributions with // very strict SELinux policies). if errors.Is(err, os.ErrPermission) { - logrus.Debugf("ignoring existing CGROUP_DEVICE program (prog_id=%v) which cannot be accessed by runc -- likely due to LSM policy: %v", progId, err) + logrus.Debugf("ignoring existing CGROUP_DEVICE program (prog_id=%v) which cannot be accessed by runc -- likely due to LSM policy: %v", progID, err) continue } return nil, fmt.Errorf("cannot fetch program from id: %w", err) } programs = append(programs, program) } - runtime.KeepAlive(progIds) + runtime.KeepAlive(progIDs) return programs, nil } diff --git a/libcontainer/cgroups/file.go b/libcontainer/cgroups/file.go index 0cdaf747849..28e0211e891 100644 --- a/libcontainer/cgroups/file.go +++ b/libcontainer/cgroups/file.go @@ -76,7 +76,7 @@ var ( // TestMode is set to true by unit tests that need "fake" cgroupfs. TestMode bool - cgroupFd int = -1 + cgroupFd = -1 prepOnce sync.Once prepErr error resolveFlags uint64 diff --git a/libcontainer/cgroups/fs/cpuacct.go b/libcontainer/cgroups/fs/cpuacct.go index d3bd7e111c7..44b53f39ce7 100644 --- a/libcontainer/cgroups/fs/cpuacct.go +++ b/libcontainer/cgroups/fs/cpuacct.go @@ -46,7 +46,7 @@ func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error { if !cgroups.PathExists(path) { return nil } - userModeUsage, kernelModeUsage, err := getCpuUsageBreakdown(path) + userModeUsage, kernelModeUsage, err := getCPUUsageBreakdown(path) if err != nil { return err } @@ -76,7 +76,7 @@ func (s *CpuacctGroup) GetStats(path string, stats *cgroups.Stats) error { } // Returns user and kernel usage breakdown in nanoseconds. -func getCpuUsageBreakdown(path string) (uint64, uint64, error) { +func getCPUUsageBreakdown(path string) (uint64, uint64, error) { var userModeUsage, kernelModeUsage uint64 const ( userField = "user" diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go index b7c75f94138..e374c43b81a 100644 --- a/libcontainer/cgroups/fs/memory.go +++ b/libcontainer/cgroups/fs/memory.go @@ -91,21 +91,15 @@ func setMemoryAndSwap(path string, r *configs.Resources) error { if err := setSwap(path, r.MemorySwap); err != nil { return err } - if err := setMemory(path, r.Memory); err != nil { - return err - } - return nil + return setMemory(path, r.Memory) } } if err := setMemory(path, r.Memory); err != nil { return err } - if err := setSwap(path, r.MemorySwap); err != nil { - return err - } - return nil + return setSwap(path, r.MemorySwap) } func (s *MemoryGroup) Set(path string, r *configs.Resources) error { diff --git a/libcontainer/cgroups/fs2/cpu.go b/libcontainer/cgroups/fs2/cpu.go index bbbae4d58c4..d0c522df849 100644 --- a/libcontainer/cgroups/fs2/cpu.go +++ b/libcontainer/cgroups/fs2/cpu.go @@ -10,12 +10,12 @@ import ( "github.com/opencontainers/runc/libcontainer/configs" ) -func isCpuSet(r *configs.Resources) bool { +func isCPUSet(r *configs.Resources) bool { return r.CpuWeight != 0 || r.CpuQuota != 0 || r.CpuPeriod != 0 } -func setCpu(dirPath string, r *configs.Resources) error { - if !isCpuSet(r) { +func setCPU(dirPath string, r *configs.Resources) error { + if !isCPUSet(r) { return nil } @@ -46,7 +46,7 @@ func setCpu(dirPath string, r *configs.Resources) error { return nil } -func statCpu(dirPath string, stats *cgroups.Stats) error { +func statCPU(dirPath string, stats *cgroups.Stats) error { const file = "cpu.stat" f, err := cgroups.OpenFile(dirPath, file, os.O_RDONLY) if err != nil { diff --git a/libcontainer/cgroups/fs2/create.go b/libcontainer/cgroups/fs2/create.go index 641123a4d84..a5e044aa677 100644 --- a/libcontainer/cgroups/fs2/create.go +++ b/libcontainer/cgroups/fs2/create.go @@ -48,7 +48,7 @@ func needAnyControllers(r *configs.Resources) (bool, error) { if isIoSet(r) && have("io") { return true, nil } - if isCpuSet(r) && have("cpu") { + if isCPUSet(r) && have("cpu") { return true, nil } if isCpusetSet(r) && have("cpuset") { @@ -65,7 +65,7 @@ func needAnyControllers(r *configs.Resources) (bool, error) { // Refer to: http://man7.org/linux/man-pages/man7/cgroups.7.html // As at Linux 4.19, the following controllers are threaded: cpu, perf_event, and pids. func containsDomainController(r *configs.Resources) bool { - return isMemorySet(r) || isIoSet(r) || isCpuSet(r) || isHugeTlbSet(r) + return isMemorySet(r) || isIoSet(r) || isCPUSet(r) || isHugeTlbSet(r) } // CreateCgroupPath creates cgroupv2 path, enabling all the supported controllers. @@ -117,13 +117,12 @@ func CreateCgroupPath(path string, c *configs.Cgroup) (Err error) { case "domain invalid": if containsDomainController(c.Resources) { return fmt.Errorf("cannot enter cgroupv2 %q with domain controllers -- it is in an invalid state", current) - } else { - // Not entirely correct (in theory we'd always want to be a domain -- - // since that means we're a properly delegated cgroup subtree) but in - // this case there's not much we can do and it's better than giving an - // error. - _ = cgroups.WriteFile(current, cgTypeFile, "threaded") } + // Not entirely correct (in theory we'd always want to be a domain -- + // since that means we're a properly delegated cgroup subtree) but in + // this case there's not much we can do and it's better than giving an + // error. + _ = cgroups.WriteFile(current, cgTypeFile, "threaded") // If the cgroup is in (threaded) or (domain threaded) mode, we can only use thread-aware controllers // (and you cannot usually take a cgroup out of threaded mode). case "domain threaded": diff --git a/libcontainer/cgroups/fs2/fs2.go b/libcontainer/cgroups/fs2/fs2.go index 492778e3105..c4a45df199e 100644 --- a/libcontainer/cgroups/fs2/fs2.go +++ b/libcontainer/cgroups/fs2/fs2.go @@ -78,10 +78,7 @@ func (m *manager) Apply(pid int) error { } return err } - if err := cgroups.WriteCgroupProc(m.dirPath, pid); err != nil { - return err - } - return nil + return cgroups.WriteCgroupProc(m.dirPath, pid) } func (m *manager) GetPids() ([]int, error) { @@ -111,7 +108,7 @@ func (m *manager) GetStats() (*cgroups.Stats, error) { } // cpu (since kernel 4.15) // Note cpu.stat is available even if the controller is not enabled. - if err := statCpu(m.dirPath, st); err != nil && !os.IsNotExist(err) { + if err := statCPU(m.dirPath, st); err != nil && !os.IsNotExist(err) { errs = append(errs, err) } // hugetlb (since kernel 5.6) @@ -167,7 +164,7 @@ func (m *manager) Set(r *configs.Resources) error { return err } // cpu (since kernel 4.15) - if err := setCpu(m.dirPath, r); err != nil { + if err := setCPU(m.dirPath, r); err != nil { return err } // devices (since kernel 4.15, pseudo-controller) diff --git a/libcontainer/cgroups/fs2/memory.go b/libcontainer/cgroups/fs2/memory.go index adbc4b23086..55ae63f0a2b 100644 --- a/libcontainer/cgroups/fs2/memory.go +++ b/libcontainer/cgroups/fs2/memory.go @@ -164,16 +164,16 @@ func statsFromMeminfo(stats *cgroups.Stats) error { // Fields we are interested in. var ( - swap_free uint64 - swap_total uint64 - main_total uint64 - main_free uint64 + swapFree uint64 + swapTotal uint64 + mainTotal uint64 + mainFree uint64 ) mem := map[string]*uint64{ - "SwapFree": &swap_free, - "SwapTotal": &swap_total, - "MemTotal": &main_total, - "MemFree": &main_free, + "SwapFree": &swapFree, + "SwapTotal": &swapTotal, + "MemTotal": &mainTotal, + "MemFree": &mainFree, } found := 0 @@ -206,10 +206,10 @@ func statsFromMeminfo(stats *cgroups.Stats) error { return &parseError{Path: "", File: file, Err: err} } - stats.MemoryStats.SwapUsage.Usage = (swap_total - swap_free) * 1024 + stats.MemoryStats.SwapUsage.Usage = (swapTotal - swapFree) * 1024 stats.MemoryStats.SwapUsage.Limit = math.MaxUint64 - stats.MemoryStats.Usage.Usage = (main_total - main_free) * 1024 + stats.MemoryStats.Usage.Usage = (mainTotal - mainFree) * 1024 stats.MemoryStats.Usage.Limit = math.MaxUint64 return nil diff --git a/libcontainer/cgroups/systemd/common.go b/libcontainer/cgroups/systemd/common.go index 98ccc51655c..1dc6cac9c75 100644 --- a/libcontainer/cgroups/systemd/common.go +++ b/libcontainer/cgroups/systemd/common.go @@ -37,13 +37,13 @@ var ( isRunningSystemd bool ) -// 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 +// +// NOTE: This function comes from package github.com/coreos/go-systemd/util +// It was borrowed here to avoid a dependency on cgo. func IsRunningSystemd() bool { isRunningSystemdOnce.Do(func() { fi, err := os.Lstat("/run/systemd/system") @@ -52,7 +52,9 @@ func IsRunningSystemd() bool { return isRunningSystemd } -// systemd represents slice hierarchy using `-`, so we need to follow suit when +// ExpandSlice expands the path of a systemd representation of a slice hierarchy. +// +// Systemd represents slice hierarchy using `-`, so we need to follow suit when // generating the path of slice. Essentially, test-a-b.slice becomes // /test.slice/test-a.slice/test-a-b.slice. func ExpandSlice(slice string) (string, error) { @@ -159,8 +161,8 @@ func findDeviceGroup(ruleType devices.Type, ruleMajor int64) (string, error) { return "", nil } -// DeviceAllow is the dbus type "a(ss)" which means we need a struct -// to represent it in Go. +// deviceAllowEntry is a type representing an entry for DeviceAllow +// dbus property value, which has dbus type of "a(ss)". type deviceAllowEntry struct { Path string Perms string @@ -459,7 +461,7 @@ func systemdVersionAtoi(verStr string) (int, error) { return ver, nil } -func addCpuQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota int64, period uint64) { +func addCPUQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota int64, period uint64) { if period != 0 { // systemd only supports CPUQuotaPeriodUSec since v242 sdVer := systemdVersion(cm) @@ -493,7 +495,7 @@ func addCpuQuota(cm *dbusConnManager, properties *[]systemdDbus.Property, quota } } -func addCpuset(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems string) error { +func addCPUSet(cm *dbusConnManager, props *[]systemdDbus.Property, cpus, mems string) error { if cpus == "" && mems == "" { return nil } diff --git a/libcontainer/cgroups/systemd/v1.go b/libcontainer/cgroups/systemd/v1.go index a74a05a5cd0..4cbf2587244 100644 --- a/libcontainer/cgroups/systemd/v1.go +++ b/libcontainer/cgroups/systemd/v1.go @@ -92,7 +92,7 @@ func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]syst newProp("CPUShares", r.CpuShares)) } - addCpuQuota(cm, &properties, r.CpuQuota, r.CpuPeriod) + addCPUQuota(cm, &properties, r.CpuQuota, r.CpuPeriod) if r.BlkioWeight != 0 { properties = append(properties, @@ -104,7 +104,7 @@ func genV1ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]syst newProp("TasksMax", uint64(r.PidsLimit))) } - err = addCpuset(cm, &properties, r.CpusetCpus, r.CpusetMems) + err = addCPUSet(cm, &properties, r.CpusetCpus, r.CpusetMems) if err != nil { return nil, err } @@ -210,11 +210,7 @@ func (m *legacyManager) Apply(pid int) error { return err } - if err := m.joinCgroups(pid); err != nil { - return err - } - - return nil + return m.joinCgroups(pid) } func (m *legacyManager) Destroy() error { diff --git a/libcontainer/cgroups/systemd/v2.go b/libcontainer/cgroups/systemd/v2.go index c31f0ecfd25..e7573871d9a 100644 --- a/libcontainer/cgroups/systemd/v2.go +++ b/libcontainer/cgroups/systemd/v2.go @@ -94,7 +94,7 @@ func unifiedResToSystemdProps(cm *dbusConnManager, res map[string]string) (props return nil, fmt.Errorf("unified resource %q quota value conversion error: %w", k, err) } } - addCpuQuota(cm, &props, quota, period) + addCPUQuota(cm, &props, quota, period) case "cpu.weight": num, err := strconv.ParseUint(v, 10, 64) @@ -210,14 +210,14 @@ func genV2ResourcesProperties(r *configs.Resources, cm *dbusConnManager) ([]syst newProp("CPUWeight", r.CpuWeight)) } - addCpuQuota(cm, &properties, r.CpuQuota, r.CpuPeriod) + addCPUQuota(cm, &properties, r.CpuQuota, r.CpuPeriod) if r.PidsLimit > 0 || r.PidsLimit == -1 { properties = append(properties, newProp("TasksMax", uint64(r.PidsLimit))) } - err = addCpuset(cm, &properties, r.CpusetCpus, r.CpusetMems) + err = addCPUSet(cm, &properties, r.CpusetCpus, r.CpusetMems) if err != nil { return nil, err } @@ -339,14 +339,8 @@ func (m *unifiedManager) Destroy() error { return err } - // systemd 239 do not remove sub-cgroups. - err := m.fsMgr.Destroy() - // fsMgr.Destroy has handled ErrNotExist - if err != nil { - return err - } - - return nil + // systemd 239 does not remove sub-cgroups. + return m.fsMgr.Destroy() } func (m *unifiedManager) Path(_ string) string { diff --git a/libcontainer/cgroups/utils.go b/libcontainer/cgroups/utils.go index 13ebf52abe4..d1744e518ed 100644 --- a/libcontainer/cgroups/utils.go +++ b/libcontainer/cgroups/utils.go @@ -18,9 +18,13 @@ import ( ) const ( - CgroupProcesses = "cgroup.procs" + cgroupProcesses = "cgroup.procs" unifiedMountpoint = "/sys/fs/cgroup" hybridMountpoint = "/sys/fs/cgroup/unified" + + // maxShares corresponds to MAX_SHARES in the Linux kernel. + // https://github.com/torvalds/linux/blob/16b3d0cf5bad844daaf436ad2e9061de0fe36e5c/kernel/sched/sched.h#L449 + maxShares = 262142 ) var ( @@ -137,7 +141,7 @@ func GetAllSubsystems() ([]string, error) { } func readProcsFile(dir string) ([]int, error) { - f, err := OpenFile(dir, CgroupProcesses, os.O_RDONLY) + f, err := OpenFile(dir, cgroupProcesses, os.O_RDONLY) if err != nil { return nil, err } @@ -383,7 +387,7 @@ func WriteCgroupProc(dir string, pid int) error { // Normally dir should not be empty, one case is that cgroup subsystem // is not mounted, we will get empty dir, and we want it fail here. if dir == "" { - return fmt.Errorf("no such directory for %s", CgroupProcesses) + return fmt.Errorf("no such directory for %s", cgroupProcesses) } // Dont attach any pid to the cgroup if -1 is specified as a pid @@ -391,7 +395,7 @@ func WriteCgroupProc(dir string, pid int) error { return nil } - file, err := OpenFile(dir, CgroupProcesses, os.O_WRONLY) + file, err := OpenFile(dir, cgroupProcesses, os.O_WRONLY) if err != nil { return fmt.Errorf("failed to write %v: %w", pid, err) } @@ -415,16 +419,20 @@ func WriteCgroupProc(dir string, pid int) error { return err } -// Since the OCI spec is designed for cgroup v1, in some cases -// there is need to convert from the cgroup v1 configuration to cgroup v2 -// the formula for cpuShares is y = (1 + ((x - 2) * 9999) / 262142) -// convert from [2-262144] to [1-10000] -// 262144 comes from Linux kernel definition "#define MAX_SHARES (1UL << 18)" +// The OCI spec is designed for cgroup v1, in some cases there is need to +// convert from the cgroup v1 configuration to cgroup v2. A few functions +// below are doing such conversion. + +// ConvertCPUSharesToCgroupV2Value converts a CPU shares cgroup v1 configuration +// to cgroup v2. +// +// The formula for CPU shares is y = (1 + ((x - 2) * 9999) / 262142) to convert +// from [2-262144] to [1-10000]. func ConvertCPUSharesToCgroupV2Value(cpuShares uint64) uint64 { if cpuShares == 0 { return 0 } - return (1 + ((cpuShares-2)*9999)/262142) + return 1 + ((cpuShares-2)*9999)/maxShares } // ConvertMemorySwapToCgroupV2Value converts MemorySwap value from OCI spec @@ -455,10 +463,11 @@ func ConvertMemorySwapToCgroupV2Value(memorySwap, memory int64) (int64, error) { return memorySwap - memory, nil } -// Since the OCI spec is designed for cgroup v1, in some cases -// there is need to convert from the cgroup v1 configuration to cgroup v2 -// the formula for BlkIOWeight to IOWeight is y = (1 + (x - 10) * 9999 / 990) -// convert linearly from [10-1000] to [1-10000] +// ConvertBlkIOToIOWeightValue converts a BlkIOWeight cgroup v1 configuration +// to cgroup v2. +// +// The formula for BlkIOWeight to IOWeight is y = (1 + (x - 10) * 9999 / 990) +// to convert linearly from [10-1000] to [1-10000]. func ConvertBlkIOToIOWeightValue(blkIoWeight uint16) uint64 { if blkIoWeight == 0 { return 0 diff --git a/libcontainer/cgroups/utils_test.go b/libcontainer/cgroups/utils_test.go index c9feb84484c..8b6377401ca 100644 --- a/libcontainer/cgroups/utils_test.go +++ b/libcontainer/cgroups/utils_test.go @@ -260,7 +260,7 @@ func TestGetCgroupMounts(t *testing.T) { } } for ss := range td.subsystems { - ss = strings.TrimPrefix(ss, CgroupNamePrefix) + ss = strings.TrimPrefix(ss, cgroupNamePrefix) m, ok := cgMap[ss] if !ok { t.Fatalf("%s not found", ss) diff --git a/libcontainer/cgroups/v1_utils.go b/libcontainer/cgroups/v1_utils.go index 47c75f22b42..ed4416a6b1c 100644 --- a/libcontainer/cgroups/v1_utils.go +++ b/libcontainer/cgroups/v1_utils.go @@ -18,12 +18,13 @@ import ( // and must not be used from any cgroup v2 code. const ( - CgroupNamePrefix = "name=" + cgroupNamePrefix = "name=" defaultPrefix = "/sys/fs/cgroup" ) var ( - errUnified = errors.New("not implemented for cgroup v2 unified hierarchy") + errUnified = errors.New("not implemented for cgroup v2 unified hierarchy") + // ErrV1NoUnified is returned when a "unified" config value is used in cgroup v1. ErrV1NoUnified = errors.New("invalid configuration: cannot use unified on cgroup v1") readMountinfoOnce sync.Once @@ -56,7 +57,7 @@ func tryDefaultPath(cgroupPath, subsystem string) string { } // remove possible prefix - subsystem = strings.TrimPrefix(subsystem, CgroupNamePrefix) + subsystem = strings.TrimPrefix(subsystem, cgroupNamePrefix) // Make sure we're still under defaultPrefix, and resolve // a possible symlink (like cpu -> cpu,cpuacct). @@ -107,7 +108,9 @@ func readCgroupMountinfo() ([]*mountinfo.Info, error) { return cgroupMountinfo, readMountinfoErr } -// https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt +// FindCgroupMountpoint returns the mountpoint for the given subsystem. +// +// See https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt. func FindCgroupMountpoint(cgroupPath, subsystem string) (string, error) { if IsCgroup2UnifiedMode() { return "", errUnified @@ -176,7 +179,7 @@ func getCgroupMountsHelper(ss map[string]bool, mounts []*mountinfo.Info, all boo continue } ss[opt] = true - opt = strings.TrimPrefix(opt, CgroupNamePrefix) + opt = strings.TrimPrefix(opt, cgroupNamePrefix) m.Subsystems = append(m.Subsystems, opt) numFound++ } @@ -282,7 +285,7 @@ func getControllerPath(subsystem string, cgroups map[string]string) (string, err return p, nil } - if p, ok := cgroups[CgroupNamePrefix+subsystem]; ok { + if p, ok := cgroups[cgroupNamePrefix+subsystem]; ok { return p, nil } diff --git a/libcontainer/configs/cgroup_linux.go b/libcontainer/configs/cgroup_linux.go index 2d4a8987109..63d56a135db 100644 --- a/libcontainer/configs/cgroup_linux.go +++ b/libcontainer/configs/cgroup_linux.go @@ -5,8 +5,10 @@ import ( "github.com/opencontainers/runc/libcontainer/devices" ) +// FreezerState is a state of the freezer cgroup. type FreezerState string +// Possible values for FreezerState. const ( Undefined FreezerState = "" Frozen FreezerState = "FROZEN" diff --git a/libcontainer/configs/config.go b/libcontainer/configs/config.go index c1b4a0041c2..c9fa838b844 100644 --- a/libcontainer/configs/config.go +++ b/libcontainer/configs/config.go @@ -42,6 +42,7 @@ type Seccomp struct { // Action is taken upon rule match in Seccomp type Action int +// Possible values for seccomp Action. const ( Kill Action = iota + 1 Errno @@ -57,6 +58,7 @@ const ( // Operator is a comparison operator to be used when matching syscall arguments in Seccomp type Operator int +// Possible values for seccomp Operator. const ( EqualTo Operator = iota + 1 NotEqualTo diff --git a/libcontainer/configs/config_linux.go b/libcontainer/configs/config_linux.go index 8c02848b70a..827a2f22245 100644 --- a/libcontainer/configs/config_linux.go +++ b/libcontainer/configs/config_linux.go @@ -3,27 +3,27 @@ package configs import "errors" var ( - errNoUIDMap = errors.New("User namespaces enabled, but no uid mappings found.") - errNoUserMap = errors.New("User namespaces enabled, but no user mapping found.") - errNoGIDMap = errors.New("User namespaces enabled, but no gid mappings found.") - errNoGroupMap = errors.New("User namespaces enabled, but no group mapping found.") + errNoUIDMap = errors.New("user namespaces enabled, but no uid mappings found") + errNoUserMap = errors.New("user namespaces enabled, but no user mapping found") + errNoGIDMap = errors.New("user namespaces enabled, but no gid mappings found") + errNoGroupMap = errors.New("user namespaces enabled, but no group mapping found") ) // HostUID gets the translated uid for the process on host which could be // different when user namespaces are enabled. -func (c Config) HostUID(containerId int) (int, error) { +func (c Config) HostUID(containerID int) (int, error) { if c.Namespaces.Contains(NEWUSER) { if c.UidMappings == nil { return -1, errNoUIDMap } - id, found := c.hostIDFromMapping(containerId, c.UidMappings) + id, found := c.hostIDFromMapping(containerID, c.UidMappings) if !found { return -1, errNoUserMap } return id, nil } // Return unchanged id. - return containerId, nil + return containerID, nil } // HostRootUID gets the root uid for the process on host which could be non-zero @@ -34,19 +34,19 @@ func (c Config) HostRootUID() (int, error) { // HostGID gets the translated gid for the process on host which could be // different when user namespaces are enabled. -func (c Config) HostGID(containerId int) (int, error) { +func (c Config) HostGID(containerID int) (int, error) { if c.Namespaces.Contains(NEWUSER) { if c.GidMappings == nil { return -1, errNoGIDMap } - id, found := c.hostIDFromMapping(containerId, c.GidMappings) + id, found := c.hostIDFromMapping(containerID, c.GidMappings) if !found { return -1, errNoGroupMap } return id, nil } // Return unchanged id. - return containerId, nil + return containerID, nil } // HostRootGID gets the root gid for the process on host which could be non-zero diff --git a/libcontainer/configs/config_test.go b/libcontainer/configs/config_test.go index 5c29b747fce..8663ec7b3b9 100644 --- a/libcontainer/configs/config_test.go +++ b/libcontainer/configs/config_test.go @@ -23,14 +23,14 @@ func TestUnmarshalHooks(t *testing.T) { Timeout: &timeout, }) - hookJson, err := json.Marshal(hookCmd) + hookJSON, err := json.Marshal(hookCmd) if err != nil { t.Fatal(err) } for _, hookName := range configs.HookNameList { hooks := configs.Hooks{} - err = hooks.UnmarshalJSON([]byte(fmt.Sprintf(`{"%s" :[%s]}`, hookName, hookJson))) + err = hooks.UnmarshalJSON([]byte(fmt.Sprintf(`{"%s" :[%s]}`, hookName, hookJSON))) if err != nil { t.Fatal(err) } @@ -74,8 +74,8 @@ func TestMarshalHooks(t *testing.T) { } // Note Marshal seems to output fields in alphabetical order - hookCmdJson := `[{"path":"/var/vcap/hooks/hook","args":["--pid=123"],"env":["FOO=BAR"],"dir":"/var/vcap","timeout":1000000000}]` - h := fmt.Sprintf(`{"createContainer":%[1]s,"createRuntime":%[1]s,"poststart":%[1]s,"poststop":%[1]s,"prestart":%[1]s,"startContainer":%[1]s}`, hookCmdJson) + hookCmdJSON := `[{"path":"/var/vcap/hooks/hook","args":["--pid=123"],"env":["FOO=BAR"],"dir":"/var/vcap","timeout":1000000000}]` + h := fmt.Sprintf(`{"createContainer":%[1]s,"createRuntime":%[1]s,"poststart":%[1]s,"poststop":%[1]s,"prestart":%[1]s,"startContainer":%[1]s}`, hookCmdJSON) if string(hooks) != h { t.Errorf("Expected hooks %s to equal %s", string(hooks), h) } @@ -164,7 +164,7 @@ func TestCommandHookRun(t *testing.T) { Bundle: "/bundle", } - stateJson, err := json.Marshal(state) + stateJSON, err := json.Marshal(state) if err != nil { t.Fatal(err) } @@ -186,9 +186,9 @@ if [ "$JSON" != "$expectedJson" ]; then fi exit 0 ` - verifyCommand := fmt.Sprintf(verifyCommandTemplate, stateJson) + verifyCommand := fmt.Sprintf(verifyCommandTemplate, stateJSON) filename := "/tmp/runc-hooktest.sh" - os.Remove(filename) + _ = os.Remove(filename) if err := os.WriteFile(filename, []byte(verifyCommand), 0o700); err != nil { t.Fatalf("Failed to create tmp file: %v", err) } diff --git a/libcontainer/configs/mount.go b/libcontainer/configs/mount.go index 784c6182051..b5d7115d257 100644 --- a/libcontainer/configs/mount.go +++ b/libcontainer/configs/mount.go @@ -5,7 +5,7 @@ import "golang.org/x/sys/unix" const ( // EXT_COPYUP is a directive to copy up the contents of a directory when // a tmpfs is mounted over it. - EXT_COPYUP = 1 << iota //nolint:golint // ignore "don't use ALL_CAPS" warning + EXT_COPYUP = 1 << iota //nolint:golint,revive // ignore "don't use ALL_CAPS" warning ) type Mount struct { diff --git a/libcontainer/configs/namespaces_linux.go b/libcontainer/configs/namespaces_linux.go index d52d6fcd147..51d09b70e6c 100644 --- a/libcontainer/configs/namespaces_linux.go +++ b/libcontainer/configs/namespaces_linux.go @@ -6,6 +6,7 @@ import ( "sync" ) +// NamespaceType constants. const ( NEWNET NamespaceType = "NEWNET" NEWPID NamespaceType = "NEWPID" @@ -21,7 +22,7 @@ var ( supportedNamespaces = make(map[NamespaceType]bool) ) -// NsName converts the namespace type to its filename +// NsName converts the namespace type to its filename. func NsName(ns NamespaceType) string { switch ns { case NEWNET: @@ -42,8 +43,7 @@ func NsName(ns NamespaceType) string { return "" } -// IsNamespaceSupported returns whether a namespace is available or -// not +// IsNamespaceSupported returns whether a namespace is available or not. func IsNamespaceSupported(ns NamespaceType) bool { nsLock.Lock() defer nsLock.Unlock() @@ -63,6 +63,7 @@ func IsNamespaceSupported(ns NamespaceType) bool { return supported } +// NamespaceTypes returns a slice of supported namespace types. func NamespaceTypes() []NamespaceType { return []NamespaceType{ NEWUSER, // Keep user NS always first, don't move it. @@ -82,6 +83,7 @@ type Namespace struct { Path string `json:"path"` } +// GetPath returns the path of the namespace. func (n *Namespace) GetPath(pid int) string { return fmt.Sprintf("/proc/%d/ns/%s", pid, NsName(n.Type)) } diff --git a/libcontainer/criu_opts_linux.go b/libcontainer/criu_opts_linux.go index b39476ef352..56b869fb7a8 100644 --- a/libcontainer/criu_opts_linux.go +++ b/libcontainer/criu_opts_linux.go @@ -1,6 +1,6 @@ package libcontainer -import criu "github.com/checkpoint-restore/go-criu/v5/rpc" +import criurpc "github.com/checkpoint-restore/go-criu/v5/rpc" type CriuPageServerInfo struct { Address string // IP address of CRIU page server @@ -24,7 +24,7 @@ type CriuOpts struct { PreDump bool // call criu predump to perform iterative checkpoint PageServer CriuPageServerInfo // allow to dump to criu page server VethPairs []VethPairName // pass the veth to criu when restore - ManageCgroupsMode criu.CriuCgMode // dump or restore cgroup mode + ManageCgroupsMode criurpc.CriuCgMode // dump or restore cgroup mode EmptyNs uint32 // don't c/r properties for namespace from this mask AutoDedup bool // auto deduplication for incremental dumps LazyPages bool // restore memory pages lazily using userfaultfd diff --git a/libcontainer/devices/device.go b/libcontainer/devices/device.go index c2c2b3bb7c0..65865694a4b 100644 --- a/libcontainer/devices/device.go +++ b/libcontainer/devices/device.go @@ -7,6 +7,7 @@ import ( ) const ( + // Wildcard is used as value for device major/minor wildcard (*). Wildcard = -1 ) @@ -100,8 +101,10 @@ func (p Permissions) IsValid() bool { return p == fromSet(p.toSet()) } +// Type describes a device type. type Type rune +// Device type values. const ( WildcardDevice Type = 'a' BlockDevice Type = 'b' diff --git a/libcontainer/error.go b/libcontainer/error.go index 510c072264f..5a0c42e5379 100644 --- a/libcontainer/error.go +++ b/libcontainer/error.go @@ -3,11 +3,11 @@ package libcontainer import "errors" var ( - ErrExist = errors.New("container with given ID already exists") - ErrInvalidID = errors.New("invalid container ID format") - ErrNotExist = errors.New("container does not exist") - ErrPaused = errors.New("container paused") - ErrRunning = errors.New("container still running") - ErrNotRunning = errors.New("container not running") - ErrNotPaused = errors.New("container not paused") + ErrExist = errors.New("container with given ID already exists") // ErrExist is returned if an ID is already in use by a container. + ErrInvalidID = errors.New("invalid container ID format") // ErrInvalidID is returned if an ID has incorrect format. + ErrNotExist = errors.New("container does not exist") // ErrNotExist is returned if an action failed because because the container does not exist. + ErrPaused = errors.New("container paused") // ErrPaused is returned if an action failed because the container is paused. + ErrRunning = errors.New("container still running") // ErrRunning is returned if an action failed because the container is still running. + ErrNotRunning = errors.New("container not running") // ErrNotRunning is returned if an action failed because the container is not running. + ErrNotPaused = errors.New("container not paused") // ErrNotPaused is returned if an action failed because the container is not paused. ) diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index 023d623f370..e6be3185c9c 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -48,7 +48,7 @@ func InitArgs(args ...string) func(*LinuxFactory) error { } } -// IntelRdtfs is an options func to configure a LinuxFactory to return +// IntelRdtFs is an options func to configure a LinuxFactory to return // containers that use the Intel RDT "resource control" filesystem to // create and manage Intel RDT resources (e.g., L3 cache, memory bandwidth). func IntelRdtFs(l *LinuxFactory) error { diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index cb862a6a5be..e62f4e8da65 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -500,9 +500,9 @@ func setupRlimits(limits []configs.Rlimit, pid int) error { return nil } -const _P_PID = 1 +const pPid = 1 // _P_PID -//nolint:structcheck,unused +//nolint:revive,structcheck,unused type siginfo struct { si_signo int32 si_errno int32 @@ -517,7 +517,7 @@ type siginfo struct { // Its based off blockUntilWaitable in src/os/wait_waitid.go func isWaitable(pid int) (bool, error) { si := &siginfo{} - _, _, e := unix.Syscall6(unix.SYS_WAITID, _P_PID, uintptr(pid), uintptr(unsafe.Pointer(si)), unix.WEXITED|unix.WNOWAIT|unix.WNOHANG, 0, 0) + _, _, e := unix.Syscall6(unix.SYS_WAITID, pPid, uintptr(pid), uintptr(unsafe.Pointer(si)), unix.WEXITED|unix.WNOWAIT|unix.WNOHANG, 0, 0) if e != 0 { return false, &os.SyscallError{Syscall: "waitid", Err: e} } diff --git a/libcontainer/integration/exec_test.go b/libcontainer/integration/exec_test.go index ada4f854b0d..f386b4daa95 100644 --- a/libcontainer/integration/exec_test.go +++ b/libcontainer/integration/exec_test.go @@ -515,18 +515,18 @@ func testFreeze(t *testing.T, withSystemd bool, useSet bool) { waitProcess(pconfig, t) } -func TestCpuShares(t *testing.T) { - testCpuShares(t, false) +func TestCPUShares(t *testing.T) { + testCPUShares(t, false) } -func TestCpuSharesSystemd(t *testing.T) { +func TestCPUSharesSystemd(t *testing.T) { if !systemd.IsRunningSystemd() { t.Skip("Test requires systemd.") } - testCpuShares(t, true) + testCPUShares(t, true) } -func testCpuShares(t *testing.T, systemd bool) { +func testCPUShares(t *testing.T, systemd bool) { if testing.Short() { return } @@ -633,7 +633,7 @@ func testCgroupResourcesUnifiedErrorOnV1(t *testing.T, systemd bool) { "memory.min": "10240", } _, _, err := runContainer(t, config, "true") - if !strings.Contains(err.Error(), cgroups.ErrV1NoUnified.Error()) { + if err == nil || !strings.Contains(err.Error(), cgroups.ErrV1NoUnified.Error()) { t.Fatalf("expected error to contain %v, got %v", cgroups.ErrV1NoUnified, err) } } @@ -728,8 +728,12 @@ func testCgroupResourcesUnified(t *testing.T, systemd bool) { continue } if err != nil { + var stdErr string + if buffers != nil { + stdErr = buffers.Stderr.String() + } t.Errorf("case %q failed: expected no error, got %v (command: %v, status: %d, stderr: %q)", - tc.name, err, tc.cmd, ret, buffers.Stderr.String()) + tc.name, err, tc.cmd, ret, stdErr) continue } if tc.exp != "" { diff --git a/libcontainer/intelrdt/cmt.go b/libcontainer/intelrdt/cmt.go index 6480a130697..56cb956ae76 100644 --- a/libcontainer/intelrdt/cmt.go +++ b/libcontainer/intelrdt/cmt.go @@ -2,7 +2,7 @@ package intelrdt var cmtEnabled bool -// Check if Intel RDT/CMT is enabled. +// IsCMTEnabled checks if Intel RDT/CMT is enabled. func IsCMTEnabled() bool { featuresInit() return cmtEnabled diff --git a/libcontainer/intelrdt/intelrdt.go b/libcontainer/intelrdt/intelrdt.go index 27cc18f688d..0927aabcbed 100644 --- a/libcontainer/intelrdt/intelrdt.go +++ b/libcontainer/intelrdt/intelrdt.go @@ -147,24 +147,24 @@ import ( */ type Manager interface { - // Applies Intel RDT configuration to the process with the specified pid + // Apply applies Intel RDT configuration to the process with the specified pid. Apply(pid int) error - // Returns statistics for Intel RDT + // GetStats returns statistics for Intel RDT. GetStats() (*Stats, error) - // Destroys the Intel RDT container-specific 'container_id' group + // Destroy destroys the Intel RDT container-specific 'container_id' group. Destroy() error - // Returns Intel RDT path to save in a state file and to be able to - // restore the object later + // GetPath returns Intel RDT path to save in a state file and to be able to + // restore the object later. GetPath() string - // Set Intel RDT "resource control" filesystem as configured. + // Set sets Intel RDT "resource control" filesystem as configured. Set(container *configs.Config) error } -// This implements interface Manager +// intelRdtManager implements interface Manager. type intelRdtManager struct { mu sync.Mutex config *configs.Config @@ -180,9 +180,7 @@ func NewManager(config *configs.Config, id string, path string) Manager { } } -const ( - intelRdtTasks = "tasks" -) +const intelRdtTasks = "tasks" var ( // The flag to indicate if Intel RDT/CAT is enabled @@ -198,7 +196,7 @@ var ( errNotFound = errors.New("Intel RDT not available") ) -// Check if Intel RDT sub-features are enabled in featuresInit() +// featuresInit checks which Intel RDT sub-features are enabled. func featuresInit() { initOnce.Do(func() { // 1. Check if Intel RDT "resource control" filesystem is available. @@ -209,7 +207,7 @@ func featuresInit() { } // 2. Check if hardware and kernel support Intel RDT sub-features. - flagsSet, err := parseCpuInfoFile("/proc/cpuinfo") + flagsSet, err := parseCPUInfoFile("/proc/cpuinfo") if err != nil { return } @@ -251,7 +249,8 @@ func featuresInit() { }) } -// Return the mount point path of Intel RDT "resource control" filesystem. +// findIntelRdtMountpointDir returns the mount point path of the Intel RDT +// "resource control" filesystem. func findIntelRdtMountpointDir() (string, error) { mi, err := mountinfo.GetMounts(func(m *mountinfo.Info) (bool, bool) { // similar to mountinfo.FSTypeFilter but stops after the first match @@ -304,17 +303,17 @@ func Root() (string, error) { } type cpuInfoFlags struct { - CAT bool // Cache Allocation Technology - MBA bool // Memory Bandwidth Allocation + CAT bool // CAT indicates whether Cache Allocation Technology is supported. + MBA bool // MBA indicates whether Memory Bandwidth Allocation is supported. // Memory Bandwidth Monitoring related. MBMTotal bool MBMLocal bool - CMT bool // Cache Monitoring Technology + CMT bool // CMT indicates whether Cache Monitoring Technology is supported. } -func parseCpuInfoFile(path string) (cpuInfoFlags, error) { +func parseCPUInfoFile(path string) (cpuInfoFlags, error) { infoFlags := cpuInfoFlags{} f, err := os.Open(path) @@ -355,7 +354,7 @@ func parseCpuInfoFile(path string) (cpuInfoFlags, error) { return infoFlags, nil } -// Gets a single uint64 value from the specified file. +// getIntelRdtParamUint returns a single uint64 value from the specified file. func getIntelRdtParamUint(path, file string) (uint64, error) { fileName := filepath.Join(path, file) contents, err := os.ReadFile(fileName) @@ -370,7 +369,7 @@ func getIntelRdtParamUint(path, file string) (uint64, error) { return res, nil } -// Gets a string value from the specified file +// getIntelRdtParamString returns a string value from the specified file. func getIntelRdtParamString(path, file string) (string, error) { contents, err := os.ReadFile(filepath.Join(path, file)) if err != nil { @@ -390,7 +389,7 @@ func writeFile(dir, file, data string) error { return nil } -// Get the read-only L3 cache information +// getL3CacheInfo returns the read-only L3 cache information. func getL3CacheInfo() (*L3CacheInfo, error) { l3CacheInfo := &L3CacheInfo{} @@ -420,7 +419,7 @@ func getL3CacheInfo() (*L3CacheInfo, error) { return l3CacheInfo, nil } -// Get the read-only memory bandwidth information +// getMemBwInfo returns the read-only memory bandwidth information. func getMemBwInfo() (*MemBwInfo, error) { memBwInfo := &MemBwInfo{} @@ -455,7 +454,8 @@ func getMemBwInfo() (*MemBwInfo, error) { return memBwInfo, nil } -// Get diagnostics for last filesystem operation error from file info/last_cmd_status +// getLastCmdStatus returns diagnostics for last filesystem operation error from +// file info/last_cmd_status. func getLastCmdStatus() (string, error) { rootPath, err := Root() if err != nil { @@ -471,7 +471,7 @@ func getLastCmdStatus() (string, error) { return lastCmdStatus, nil } -// WriteIntelRdtTasks writes the specified pid into the "tasks" file +// WriteIntelRdtTasks writes the specified pid into the "tasks" file. func WriteIntelRdtTasks(dir string, pid int) error { if dir == "" { return fmt.Errorf("no such directory for %s", intelRdtTasks) @@ -486,25 +486,26 @@ func WriteIntelRdtTasks(dir string, pid int) error { return nil } -// Check if Intel RDT/CAT is enabled +// IsCATEnabled checks if Intel RDT/CAT is enabled. func IsCATEnabled() bool { featuresInit() return catEnabled } -// Check if Intel RDT/MBA is enabled +// IsMBAEnabled checks if Intel RDT/MBA is enabled. func IsMBAEnabled() bool { featuresInit() return mbaEnabled } -// Check if Intel RDT/MBA Software Controller is enabled +// IsMBAScEnabled checks if Intel RDT/MBA Software Controller is enabled. func IsMBAScEnabled() bool { featuresInit() return mbaScEnabled } -// Get the path of the clos group in "resource control" filesystem that the container belongs to +// getIntelRdtPath returns the path of the clos group in "resource control" +// filesystem that the container belongs to. func (m *intelRdtManager) getIntelRdtPath() (string, error) { rootPath, err := Root() if err != nil { @@ -519,7 +520,7 @@ func (m *intelRdtManager) getIntelRdtPath() (string, error) { return filepath.Join(rootPath, clos), nil } -// Applies Intel RDT configuration to the process with the specified pid +// Apply applies Intel RDT configuration to the process with the specified pid. func (m *intelRdtManager) Apply(pid int) (err error) { // If intelRdt is not specified in config, we do nothing if m.config.IntelRdt == nil { @@ -554,7 +555,7 @@ func (m *intelRdtManager) Apply(pid int) (err error) { return nil } -// Destroys the Intel RDT container-specific 'container_id' group +// Destroy destroys the Intel RDT container-specific 'container_id' group. func (m *intelRdtManager) Destroy() error { // Don't remove resctrl group if closid has been explicitly specified. The // group is likely externally managed, i.e. by some other entity than us. @@ -570,8 +571,8 @@ func (m *intelRdtManager) Destroy() error { return nil } -// Returns Intel RDT path to save in a state file and to be able to -// restore the object later +// GetPath returns Intel RDT path to save in a state file and to be able to +// restore the object later. func (m *intelRdtManager) GetPath() string { if m.path == "" { m.path, _ = m.getIntelRdtPath() @@ -579,7 +580,7 @@ func (m *intelRdtManager) GetPath() string { return m.path } -// Returns statistics for Intel RDT +// GetStats returns statistics for Intel RDT. func (m *intelRdtManager) GetStats() (*Stats, error) { // If intelRdt is not specified in config if m.config.IntelRdt == nil { @@ -665,7 +666,7 @@ func (m *intelRdtManager) GetStats() (*Stats, error) { return stats, nil } -// Set Intel RDT "resource control" filesystem as configured. +// Set sets Intel RDT "resource control" filesystem as configured. func (m *intelRdtManager) Set(container *configs.Config) error { // About L3 cache schema: // It has allocation bitmasks/values for L3 cache on each socket, diff --git a/libcontainer/intelrdt/intelrdt_test.go b/libcontainer/intelrdt/intelrdt_test.go index 2184a1468df..8d6760dc85c 100644 --- a/libcontainer/intelrdt/intelrdt_test.go +++ b/libcontainer/intelrdt/intelrdt_test.go @@ -8,7 +8,7 @@ import ( ) func TestIntelRdtSetL3CacheSchema(t *testing.T) { - helper := NewIntelRdtTestUtil(t) + helper := newIntelRdtTestUtil(t) const ( l3CacheSchemaBefore = "L3:0=f;1=f0" @@ -38,7 +38,7 @@ func TestIntelRdtSetL3CacheSchema(t *testing.T) { } func TestIntelRdtSetMemBwSchema(t *testing.T) { - helper := NewIntelRdtTestUtil(t) + helper := newIntelRdtTestUtil(t) const ( memBwSchemaBefore = "MB:0=20;1=70" @@ -68,7 +68,7 @@ func TestIntelRdtSetMemBwSchema(t *testing.T) { } func TestIntelRdtSetMemBwScSchema(t *testing.T) { - helper := NewIntelRdtTestUtil(t) + helper := newIntelRdtTestUtil(t) const ( memBwScSchemaBefore = "MB:0=5000;1=7000" @@ -98,7 +98,7 @@ func TestIntelRdtSetMemBwScSchema(t *testing.T) { } func TestApply(t *testing.T) { - helper := NewIntelRdtTestUtil(t) + helper := newIntelRdtTestUtil(t) const closID = "test-clos" diff --git a/libcontainer/intelrdt/mbm.go b/libcontainer/intelrdt/mbm.go index 13f31ac7a08..ca3a58c0f62 100644 --- a/libcontainer/intelrdt/mbm.go +++ b/libcontainer/intelrdt/mbm.go @@ -1,9 +1,9 @@ package intelrdt -// The flag to indicate if Intel RDT/MBM is enabled +// mbmEnabled indicates if Intel RDT/MBM is enabled. var mbmEnabled bool -// Check if Intel RDT/MBM is enabled. +// IsMBMEnabled checks if Intel RDT/MBM is enabled. func IsMBMEnabled() bool { featuresInit() return mbmEnabled diff --git a/libcontainer/intelrdt/util_test.go b/libcontainer/intelrdt/util_test.go index b29d685e981..2ee2b4cc81e 100644 --- a/libcontainer/intelrdt/util_test.go +++ b/libcontainer/intelrdt/util_test.go @@ -15,14 +15,14 @@ import ( type intelRdtTestUtil struct { config *configs.Config - // Path to the mock Intel RDT "resource control" filesystem directory + // IntelRdtPath is the path to the mock Intel RDT "resource control" filesystem directory. IntelRdtPath string t *testing.T } -// Creates a new test util -func NewIntelRdtTestUtil(t *testing.T) *intelRdtTestUtil { +// newIntelRdtTestUtil creates a new test util. +func newIntelRdtTestUtil(t *testing.T) *intelRdtTestUtil { config := &configs.Config{ IntelRdt: &configs.IntelRdt{}, } diff --git a/libcontainer/notify_linux.go b/libcontainer/notify_linux.go index a8762842e8f..7380283b6f9 100644 --- a/libcontainer/notify_linux.go +++ b/libcontainer/notify_linux.go @@ -9,8 +9,10 @@ import ( "golang.org/x/sys/unix" ) +// PressureLevel is used for memory pressure levels. type PressureLevel uint +// PressureLevel values. const ( LowPressure PressureLevel = iota MediumPressure diff --git a/libcontainer/rootfs_linux.go b/libcontainer/rootfs_linux.go index 51660f5efb9..f23292fd0bb 100644 --- a/libcontainer/rootfs_linux.go +++ b/libcontainer/rootfs_linux.go @@ -245,11 +245,7 @@ func prepareBindMount(m *configs.Mount, rootfs string, mountFd *int) error { if err := checkProcMount(rootfs, dest, source); err != nil { return err } - if err := createIfNotExists(dest, stat.IsDir()); err != nil { - return err - } - - return nil + return createIfNotExists(dest, stat.IsDir()) } func mountCgroupV1(m *configs.Mount, c *mountConfig) error { @@ -293,7 +289,7 @@ func mountCgroupV1(m *configs.Mount, c *mountConfig) error { data = filepath.Base(subsystemPath) ) if data == "systemd" { - data = cgroups.CgroupNamePrefix + data + data = "name=" + data source = "systemd" } return mount(source, b.Destination, procfd, "cgroup", uintptr(flags), data) @@ -939,12 +935,11 @@ func msMoveRoot(rootfs string) error { if err := unmount(p, unix.MNT_DETACH); err != nil { if !errors.Is(err, unix.EINVAL) && !errors.Is(err, unix.EPERM) { return err - } else { - // If we have not privileges for umounting (e.g. rootless), then - // cover the path. - if err := mount("tmpfs", p, "", "tmpfs", 0, ""); err != nil { - return err - } + } + // If we have not privileges for umounting (e.g. rootless), then + // cover the path. + if err := mount("tmpfs", p, "", "tmpfs", 0, ""); err != nil { + return err } } } diff --git a/libcontainer/seccomp/seccomp_linux.go b/libcontainer/seccomp/seccomp_linux.go index f177b7f05f2..baa9d78ea5a 100644 --- a/libcontainer/seccomp/seccomp_linux.go +++ b/libcontainer/seccomp/seccomp_linux.go @@ -226,7 +226,7 @@ func matchCall(filter *libseccomp.ScmpFilter, call *configs.Syscall, defAct libs return fmt.Errorf("error creating seccomp syscall condition for syscall %s: %w", call.Name, err) } - argCounts[cond.Index] += 1 + argCounts[cond.Index]++ conditions = append(conditions, newCond) } diff --git a/libcontainer/specconv/spec_linux_test.go b/libcontainer/specconv/spec_linux_test.go index 56d808699c6..d11983eefc1 100644 --- a/libcontainer/specconv/spec_linux_test.go +++ b/libcontainer/specconv/spec_linux_test.go @@ -812,8 +812,8 @@ func TestCreateDevices(t *testing.T) { // dummy uid/gid for /dev/tty; will enable the test to check if createDevices() // preferred the spec's device over the redundant default device - ttyUid := uint32(1000) - ttyGid := uint32(1000) + ttyUID := uint32(1000) + ttyGID := uint32(1000) fm := os.FileMode(0o666) spec.Linux = &specs.Linux{ @@ -825,8 +825,8 @@ func TestCreateDevices(t *testing.T) { Major: 5, Minor: 0, FileMode: &fm, - UID: &ttyUid, - GID: &ttyGid, + UID: &ttyUID, + GID: &ttyGID, }, { // This is purposely not redundant with one of runc's default devices diff --git a/libcontainer/standard_init_linux.go b/libcontainer/standard_init_linux.go index 585a04fa080..3308df41928 100644 --- a/libcontainer/standard_init_linux.go +++ b/libcontainer/standard_init_linux.go @@ -54,7 +54,7 @@ func (l *linuxStandardInit) Init() error { ringname, keepperms, newperms := l.getSessionRingParams() // Do not inherit the parent's session keyring. - if sessKeyId, err := keys.JoinSessionKeyring(ringname); err != nil { + if sessKeyID, err := keys.JoinSessionKeyring(ringname); err != nil { // If keyrings aren't supported then it is likely we are on an // older kernel (or inside an LXC container). While we could bail, // the security feature we are using here is best-effort (it only @@ -70,7 +70,7 @@ func (l *linuxStandardInit) Init() error { // Make session keyring searchable. If we've gotten this far we // bail on any error -- we don't want to have a keyring with bad // permissions. - if err := keys.ModKeyringPerm(sessKeyId, keepperms, newperms); err != nil { + if err := keys.ModKeyringPerm(sessKeyID, keepperms, newperms); err != nil { return fmt.Errorf("unable to mod keyring permissions: %w", err) } } diff --git a/libcontainer/state_linux.go b/libcontainer/state_linux.go index aa6259b157d..c6b46f22200 100644 --- a/libcontainer/state_linux.go +++ b/libcontainer/state_linux.go @@ -71,11 +71,7 @@ func runPoststopHooks(c *linuxContainer) error { } s.Status = specs.StateStopped - if err := hooks[configs.Poststop].RunHooks(s); err != nil { - return err - } - - return nil + return hooks[configs.Poststop].RunHooks(s) } // stoppedState represents a container is a stopped/destroyed state. diff --git a/libcontainer/system/linux.go b/libcontainer/system/linux.go index e1d6eb18034..464ca74cb5d 100644 --- a/libcontainer/system/linux.go +++ b/libcontainer/system/linux.go @@ -50,10 +50,7 @@ func Exec(cmd string, args []string, env []string) error { } func SetParentDeathSignal(sig uintptr) error { - if err := unix.Prctl(unix.PR_SET_PDEATHSIG, sig, 0, 0, 0); err != nil { - return err - } - return nil + return unix.Prctl(unix.PR_SET_PDEATHSIG, sig, 0, 0, 0) } func GetParentDeathSignal() (ParentDeathSignal, error) { @@ -65,26 +62,15 @@ func GetParentDeathSignal() (ParentDeathSignal, error) { } func SetKeepCaps() error { - if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 1, 0, 0, 0); err != nil { - return err - } - - return nil + return unix.Prctl(unix.PR_SET_KEEPCAPS, 1, 0, 0, 0) } func ClearKeepCaps() error { - if err := unix.Prctl(unix.PR_SET_KEEPCAPS, 0, 0, 0, 0); err != nil { - return err - } - - return nil + return unix.Prctl(unix.PR_SET_KEEPCAPS, 0, 0, 0, 0) } func Setctty() error { - if err := unix.IoctlSetInt(0, unix.TIOCSCTTY, 0); err != nil { - return err - } - return nil + return unix.IoctlSetInt(0, unix.TIOCSCTTY, 0) } // SetSubreaper sets the value i as the subreaper setting for the calling process diff --git a/libcontainer/system/proc.go b/libcontainer/system/proc.go index 774443ec9d2..b9c4e198ed4 100644 --- a/libcontainer/system/proc.go +++ b/libcontainer/system/proc.go @@ -11,7 +11,9 @@ import ( // State is the status of a process. type State rune -const ( // Only values for Linux 3.14 and later are listed here +// Process state values. +// Only values for Linux 3.14 and later are listed here. +const ( Dead State = 'X' DiskSleep State = 'D' Running State = 'R' diff --git a/libcontainer/utils/cmsg.go b/libcontainer/utils/cmsg.go index 7ef9da21fd2..fd9326cb59a 100644 --- a/libcontainer/utils/cmsg.go +++ b/libcontainer/utils/cmsg.go @@ -23,7 +23,7 @@ import ( "golang.org/x/sys/unix" ) -// MaxSendfdLen is the maximum length of the name of a file descriptor being +// MaxNameLen is the maximum length of the name of a file descriptor being // sent using SendFd. The name of the file handle returned by RecvFd will never // be larger than this value. const MaxNameLen = 4096 diff --git a/notify_socket.go b/notify_socket.go index 76aa27ca518..70bc8e0c59f 100644 --- a/notify_socket.go +++ b/notify_socket.go @@ -91,19 +91,19 @@ func notifySocketStart(context *cli.Context, notifySocketHost, id string) (*noti return notifySocket, nil } -func (n *notifySocket) waitForContainer(container libcontainer.Container) error { - s, err := container.State() +func (s *notifySocket) waitForContainer(container libcontainer.Container) error { + cs, err := container.State() if err != nil { return err } - return n.run(s.InitProcessPid) + return s.run(cs.InitProcessPid) } -func (n *notifySocket) run(pid1 int) error { - if n.socket == nil { +func (s *notifySocket) run(pid1 int) error { + if s.socket == nil { return nil } - notifySocketHostAddr := net.UnixAddr{Name: n.host, Net: "unixgram"} + notifySocketHostAddr := net.UnixAddr{Name: s.host, Net: "unixgram"} client, err := net.DialUnix("unixgram", nil, ¬ifySocketHostAddr) if err != nil { return err @@ -116,7 +116,7 @@ func (n *notifySocket) run(pid1 int) error { go func() { for { buf := make([]byte, 4096) - r, err := n.socket.Read(buf) + r, err := s.socket.Read(buf) if err != nil { return } diff --git a/restore.go b/restore.go index 59d2904ec94..dd2c8b6d715 100644 --- a/restore.go +++ b/restore.go @@ -113,7 +113,7 @@ using the runc checkpoint command.`, if err := setEmptyNsMask(context, options); err != nil { return err } - status, err := startContainer(context, CT_ACT_RESTORE, options) + status, err := startContainer(context, actRestore, options) if err != nil { return err } diff --git a/run.go b/run.go index 82781669d10..abc22432507 100644 --- a/run.go +++ b/run.go @@ -69,7 +69,7 @@ command(s) that get executed on start, edit the args parameter of the spec. See if err := checkArgs(context, 1, exactArgs); err != nil { return err } - status, err := startContainer(context, CT_ACT_RUN, nil) + status, err := startContainer(context, actRun, nil) if err == nil { // exit with the container's exit status so any external supervisor is // notified of the exit with the correct exit status. diff --git a/types/events.go b/types/events.go index 81bde829da5..a2f57461e9d 100644 --- a/types/events.go +++ b/types/events.go @@ -9,7 +9,8 @@ type Event struct { Data interface{} `json:"data,omitempty"` } -// stats is the runc specific stats structure for stability when encoding and decoding stats. +// Stats is the runc specific stats structure for stability when encoding and +// decoding stats. type Stats struct { CPU Cpu `json:"cpu"` CPUSet CPUSet `json:"cpuset"` @@ -115,28 +116,30 @@ type MemBwInfo struct { } type IntelRdt struct { - // The read-only L3 cache information + // L3CacheInfo holds read-only L3 cache information. L3CacheInfo *L3CacheInfo `json:"l3_cache_info,omitempty"` - // The read-only L3 cache schema in root + // L3CacheSchemaRoot holds the read-only L3 cache schema in root. L3CacheSchemaRoot string `json:"l3_cache_schema_root,omitempty"` - // The L3 cache schema in 'container_id' group + // L3CacheSchema holds the L3 cache schema in 'container_id' group. L3CacheSchema string `json:"l3_cache_schema,omitempty"` - // The read-only memory bandwidth information + // MemBwInfo holds read-only memory bandwidth information. MemBwInfo *MemBwInfo `json:"mem_bw_info,omitempty"` - // The read-only memory bandwidth schema in root + // MemBwSchemaRoot holds the read-only memory bandwidth schema in root. MemBwSchemaRoot string `json:"mem_bw_schema_root,omitempty"` - // The memory bandwidth schema in 'container_id' group + // MemBwSchema hold the memory bandwidth schema in 'container_id' group. MemBwSchema string `json:"mem_bw_schema,omitempty"` - // The memory bandwidth monitoring statistics from NUMA nodes in 'container_id' group + // MBMStats holds the memory bandwidth monitoring statistics from NUMA nodes + // in 'container_id' group. MBMStats *[]intelrdt.MBMNumaNodeStats `json:"mbm_stats,omitempty"` - // The cache monitoring technology statistics from NUMA nodes in 'container_id' group + // CMTStats holds the cache monitoring technology statistics from NUMA nodes + // in 'container_id' group. CMTStats *[]intelrdt.CMTNumaNodeStats `json:"cmt_stats,omitempty"` } diff --git a/utils_linux.go b/utils_linux.go index a9badf20f8b..69dc62d9e52 100644 --- a/utils_linux.go +++ b/utils_linux.go @@ -229,7 +229,7 @@ type runner struct { pidFile string consoleSocket string container libcontainer.Container - action CtAct + action ctAct notifySocket *notifySocket criuOpts *libcontainer.CriuOpts subCgroupPaths map[string]string @@ -273,7 +273,7 @@ func (r *runner) run(config *specs.Process) (int, error) { if err != nil { return -1, err } - detach := r.detach || (r.action == CT_ACT_CREATE) + detach := r.detach || (r.action == actCreate) // Setting up IO is a two stage process. We need to modify process to deal // with detaching containers, and then we get a tty after the container has // started. @@ -285,11 +285,11 @@ func (r *runner) run(config *specs.Process) (int, error) { defer tty.Close() switch r.action { - case CT_ACT_CREATE: + case actCreate: err = r.container.Start(process) - case CT_ACT_RESTORE: + case actRestore: err = r.container.Restore(process, r.criuOpts) - case CT_ACT_RUN: + case actRun: err = r.container.Run(process) default: panic("Unknown action") @@ -333,7 +333,7 @@ func (r *runner) terminate(p *libcontainer.Process) { } func (r *runner) checkTerminal(config *specs.Process) error { - detach := r.detach || (r.action == CT_ACT_CREATE) + detach := r.detach || (r.action == actCreate) // Check command-line for sanity. if detach && config.Terminal && r.consoleSocket == "" { return errors.New("cannot allocate tty if runc will detach without setting console socket") @@ -363,15 +363,15 @@ func validateProcessSpec(spec *specs.Process) error { return nil } -type CtAct uint8 +type ctAct uint8 const ( - CT_ACT_CREATE CtAct = iota + 1 - CT_ACT_RUN - CT_ACT_RESTORE + actCreate ctAct = iota + 1 // Create container + actRun // Run container + actRestore // Restore container ) -func startContainer(context *cli.Context, action CtAct, criuOpts *libcontainer.CriuOpts) (int, error) { +func startContainer(context *cli.Context, action ctAct, criuOpts *libcontainer.CriuOpts) (int, error) { if err := revisePidFile(context); err != nil { return -1, err } @@ -399,7 +399,7 @@ func startContainer(context *cli.Context, action CtAct, criuOpts *libcontainer.C if err := notifySocket.setupSocketDirectory(); err != nil { return -1, err } - if action == CT_ACT_RUN { + if action == actRun { if err := notifySocket.bindSocket(); err != nil { return -1, err }