diff --git a/libcontainer/error.go b/libcontainer/error.go index bd5ad1f8bf7..cb1532b5e4b 100644 --- a/libcontainer/error.go +++ b/libcontainer/error.go @@ -10,6 +10,7 @@ var ( ErrRunning = errors.New("container still running") ErrNotRunning = errors.New("container not running") ErrNotPaused = errors.New("container not paused") + ErrCgExist = errors.New("container's cgroup already exists") ) type ConfigError struct { diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index 522bf1de667..77d926f5dfc 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -160,14 +160,19 @@ func (l *LinuxFactory) Create(id string, config *configs.Config) (Container, err } else if !os.IsNotExist(err) { return nil, err } - if err := os.MkdirAll(containerRoot, 0o711); err != nil { + + cm, err := manager.New(config.Cgroups) + if err != nil { return nil, err } - if err := os.Chown(containerRoot, unix.Geteuid(), unix.Getegid()); err != nil { + if cm.Exists() { + return nil, ErrCgExist + } + + if err := os.MkdirAll(containerRoot, 0o711); err != nil { return nil, err } - cm, err := manager.New(config.Cgroups) - if err != nil { + if err := os.Chown(containerRoot, unix.Geteuid(), unix.Getegid()); err != nil { return nil, err } c := &linuxContainer{ diff --git a/tests/integration/cgroups.bats b/tests/integration/cgroups.bats index 7b8603db867..ecd2c04961b 100644 --- a/tests/integration/cgroups.bats +++ b/tests/integration/cgroups.bats @@ -301,3 +301,24 @@ function setup() { [ "$status" -eq 255 ] [[ "$output" == *"container cgroup is frozen"* ]] } + +@test "runc run/create should refuse an existing cgroup" { + if [[ "$ROOTLESS" -ne 0 ]]; then + requires rootless_cgroup + fi + + set_cgroups_path + + runc run -d --console-socket "$CONSOLE_SOCKET" ct1 + [ "$status" -eq 0 ] + + # Run a second container sharing the cgroup with the first one. + runc --debug run -d --console-socket "$CONSOLE_SOCKET" ct2 + [ "$status" -ne 0 ] + [[ "$output" == *"container's cgroup already exists"* ]] + + # Same but using runc create. + runc create --console-socket "$CONSOLE_SOCKET" ct3 + [ "$status" -ne 0 ] + [[ "$output" == *"container's cgroup already exists"* ]] +}