From a4518408d96ad2f6dd13ce47938be56619493b94 Mon Sep 17 00:00:00 2001 From: Tibor Vass Date: Thu, 22 Jun 2017 21:17:20 -0700 Subject: [PATCH] Do not cast -1 to uint64 in EnableKernelMemoryAccounting This fixes a runc bug that is very annoying on kernels such as RHEL 7.2 that have the following bug: when setting memory.kmem.limit_in_bytes to a bigger value than the default max value (bigger than 2^63-1), the buggy kernel sets it to 0, instead of setting it to the max value. This results in the process being unable to run with a 0 byte limit on kmem. That kernel bug exposes a runc bug introduced in 8430cc4, that casted an int64(-1) to uint64 in EnableKernelMemoryAccounting, which is called every time the user specifies any memory-related cgroup setting as determined by the memoryAssigned function. This patch is the smallest fix for this clearly unwanted behavior. Reverting 8430cc4, although desirable because int64 values are casted to uint64 in many other places introducing similar bugs, it is out of scope for this patch since it would require a spec change. Signed-off-by: Tibor Vass --- libcontainer/cgroups/fs/memory.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libcontainer/cgroups/fs/memory.go b/libcontainer/cgroups/fs/memory.go index da2cc9f8b6f..d446787056d 100644 --- a/libcontainer/cgroups/fs/memory.go +++ b/libcontainer/cgroups/fs/memory.go @@ -73,14 +73,14 @@ func EnableKernelMemoryAccounting(path string) error { // until a limit is set on the cgroup and limit cannot be set once the // cgroup has children, or if there are already tasks in the cgroup. for _, i := range []int64{1, -1} { - if err := setKernelMemory(path, uint64(i)); err != nil { + if err := setKernelMemory(path, i); err != nil { return err } } return nil } -func setKernelMemory(path string, kernelMemoryLimit uint64) error { +func setKernelMemory(path string, kernelMemoryLimit int64) error { if path == "" { return fmt.Errorf("no such directory for %s", cgroupKernelMemoryLimit) } @@ -88,7 +88,7 @@ func setKernelMemory(path string, kernelMemoryLimit uint64) error { // kernel memory is not enabled on the system so we should do nothing return nil } - if err := ioutil.WriteFile(filepath.Join(path, cgroupKernelMemoryLimit), []byte(strconv.FormatUint(kernelMemoryLimit, 10)), 0700); err != nil { + if err := ioutil.WriteFile(filepath.Join(path, cgroupKernelMemoryLimit), []byte(strconv.FormatInt(kernelMemoryLimit, 10)), 0700); err != nil { // Check if the error number returned by the syscall is "EBUSY" // The EBUSY signal is returned on attempts to write to the // memory.kmem.limit_in_bytes file if the cgroup has children or @@ -165,7 +165,7 @@ func (s *MemoryGroup) Set(path string, cgroup *configs.Cgroup) error { } if cgroup.Resources.KernelMemory != 0 { - if err := setKernelMemory(path, cgroup.Resources.KernelMemory); err != nil { + if err := setKernelMemory(path, int64(cgroup.Resources.KernelMemory)); err != nil { return err } }