Skip to content

Commit a82146f

Browse files
committed
libct: use manager.AddPid to add exec to cgroup
The main benefit here is when we are using a systemd cgroup driver, we actually ask systemd to add a PID, rather than doing it ourselves. This way, we can add rootless exec PID to a cgroup. The implementation requires opencontainers/cgroups#26. Signed-off-by: Kir Kolyshkin <[email protected]>
1 parent 94d16c9 commit a82146f

File tree

13 files changed

+125
-26
lines changed

13 files changed

+125
-26
lines changed

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,8 @@ require (
3232
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
3333
github.com/russross/blackfriday/v2 v2.1.0 // indirect
3434
)
35+
36+
replace (
37+
github.com/coreos/go-systemd/v22 => github.com/kolyshkin/go-systemd/v22 v22.5.1-0.20250725225557-871b63ece367
38+
github.com/opencontainers/cgroups => github.com/kolyshkin/oc-cgroups v0.0.5-0.20250728222832-ba8c4b2abb82
39+
)

go.sum

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,6 @@ github.com/cilium/ebpf v0.17.3 h1:FnP4r16PWYSE4ux6zN+//jMcW4nMVRvuTLVTvCjyyjg=
55
github.com/cilium/ebpf v0.17.3/go.mod h1:G5EDHij8yiLzaqn0WjyfJHvRa+3aDlReIaLVRMvOyJk=
66
github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc=
77
github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
8-
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
9-
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
108
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
119
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
1210
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
@@ -18,7 +16,6 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
1816
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
1917
github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI=
2018
github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow=
21-
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
2219
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
2320
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
2421
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
@@ -27,6 +24,10 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
2724
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
2825
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
2926
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
27+
github.com/kolyshkin/go-systemd/v22 v22.5.1-0.20250725225557-871b63ece367 h1:kJ57mQymQQXt6NY3pnLdHgEyTYtMFnoyAXgAMdXdp1U=
28+
github.com/kolyshkin/go-systemd/v22 v22.5.1-0.20250725225557-871b63ece367/go.mod h1:m2r/smMKsKwgMSAoFKHaa68ImdCSNuKE1MxvQ64xuCQ=
29+
github.com/kolyshkin/oc-cgroups v0.0.5-0.20250728222832-ba8c4b2abb82 h1:Bbce2cBpWLu0PI2JjkFo5X1+y2p1mh9kf5XG12BbsQw=
30+
github.com/kolyshkin/oc-cgroups v0.0.5-0.20250728222832-ba8c4b2abb82/go.mod h1:xHZu7XMu81ZxdNLkjJSH+FvVkwlpCfEHh/bLaDQLm2U=
3031
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
3132
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
3233
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@@ -45,8 +46,6 @@ github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g
4546
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
4647
github.com/mrunalp/fileutils v0.5.1 h1:F+S7ZlNKnrwHfSwdlgNSkKo67ReVf8o9fel6C3dkm/Q=
4748
github.com/mrunalp/fileutils v0.5.1/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
48-
github.com/opencontainers/cgroups v0.0.4 h1:XVj8P/IHVms/j+7eh8ggdkTLAxjz84ZzuFyGoE28DR4=
49-
github.com/opencontainers/cgroups v0.0.4/go.mod h1:s8lktyhlGUqM7OSRL5P7eAW6Wb+kWPNvt4qvVfzA5vs=
5049
github.com/opencontainers/runtime-spec v1.2.2-0.20250401095657-e935f995dd67 h1:Q+KewUGTMamIe6Q39xCD/T1NC1POmaTlWnhjikCrZHA=
5150
github.com/opencontainers/runtime-spec v1.2.2-0.20250401095657-e935f995dd67/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
5251
github.com/opencontainers/selinux v1.12.0 h1:6n5JV4Cf+4y0KNXW48TLj5DwfXpvWlxXplUkdTrmPb8=

libcontainer/container_linux_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func (m *mockCgroupManager) Apply(pid int) error {
3232
return nil
3333
}
3434

35+
func (m *mockCgroupManager) AddPid(_ string, _ int) error {
36+
return nil
37+
}
38+
3539
func (m *mockCgroupManager) Set(_ *cgroups.Resources) error {
3640
return nil
3741
}

libcontainer/process_linux.go

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,18 @@ func (p *setnsProcess) setFinalCPUAffinity() error {
201201
}
202202

203203
func (p *setnsProcess) addIntoCgroupV1() error {
204+
if sub, ok := p.process.SubCgroupPaths[""]; ok || len(p.process.SubCgroupPaths) == 0 {
205+
// Either same sub-cgroup for all paths, or no sub-cgroup.
206+
err := p.manager.AddPid(sub, p.pid())
207+
if err != nil && !p.rootlessCgroups {
208+
return fmt.Errorf("error adding pid %d to cgroups: %w", p.pid(), err)
209+
}
210+
return nil
211+
}
212+
213+
// Per-controller sub-cgroup paths. Not supported by AddPid (or systemd),
214+
// so we have to calculate and check all sub-cgroup paths, and write
215+
// directly to cgroupfs.
204216
paths := maps.Clone(p.manager.GetPaths())
205217
for ctrl, sub := range p.process.SubCgroupPaths {
206218
base, ok := paths[ctrl]
@@ -209,7 +221,7 @@ func (p *setnsProcess) addIntoCgroupV1() error {
209221
}
210222
cgPath := path.Join(base, sub)
211223
if !strings.HasPrefix(cgPath, base) {
212-
return fmt.Errorf("%s is not a sub cgroup path", sub)
224+
return fmt.Errorf("bad sub cgroup path: %s", sub)
213225
}
214226
paths[ctrl] = cgPath
215227
}
@@ -224,18 +236,10 @@ func (p *setnsProcess) addIntoCgroupV1() error {
224236
}
225237

226238
func (p *setnsProcess) addIntoCgroupV2() error {
227-
base := p.manager.Path("")
228-
sub := ""
229-
if p.process.SubCgroupPaths != nil {
230-
sub = p.process.SubCgroupPaths[""]
231-
}
232-
cgPath := path.Join(base, sub)
233-
if !strings.HasPrefix(cgPath, base) {
234-
return fmt.Errorf("%s is not a sub cgroup path", sub)
235-
}
236-
237-
if err := cgroups.WriteCgroupProc(cgPath, p.pid()); err != nil && !p.rootlessCgroups {
238-
// On cgroup v2 + nesting + domain controllers, WriteCgroupProc may fail with EBUSY.
239+
sub := p.process.SubCgroupPaths[""]
240+
err := p.manager.AddPid(sub, p.pid())
241+
if err != nil && !p.rootlessCgroups {
242+
// On cgroup v2 + nesting + domain controllers, adding to initial cgroup may fail with EBUSY.
239243
// https://github.com/opencontainers/runc/issues/2356#issuecomment-621277643
240244
// Try to join the cgroup of InitProcessPid, unless sub-cgroup is explicitly set.
241245
if p.initProcessPid != 0 && sub == "" {
@@ -244,8 +248,8 @@ func (p *setnsProcess) addIntoCgroupV2() error {
244248
if initCgErr == nil {
245249
if initCgPath, ok := initCg[""]; ok {
246250
initCgDirpath := filepath.Join(fs2.UnifiedMountpoint, initCgPath)
247-
logrus.Debugf("adding pid %d to cgroup %s failed (%v), attempting to join %s",
248-
p.pid(), cgPath, err, initCgDirpath)
251+
logrus.Debugf("adding pid %d to cgroup failed (%v), attempting to join %s",
252+
p.pid(), err, initCgDirpath)
249253
// NOTE: initCgDirPath is not guaranteed to exist because we didn't pause the container.
250254
err = cgroups.WriteCgroupProc(initCgDirpath, p.pid())
251255
}

tests/integration/exec.bats

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ function check_exec_debug() {
226226
# Check we can't join parent cgroup.
227227
runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
228228
[ "$status" -ne 0 ]
229-
[[ "$output" == *" .. is not a sub cgroup path"* ]]
229+
[[ "$output" == *"bad sub cgroup path"* ]]
230230

231231
# Check we can't join non-existing subcgroup.
232232
runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
@@ -277,12 +277,12 @@ function check_exec_debug() {
277277
# Check we can't join parent cgroup.
278278
runc exec --cgroup ".." test_busybox cat /proc/self/cgroup
279279
[ "$status" -ne 0 ]
280-
[[ "$output" == *" .. is not a sub cgroup path"* ]]
280+
[[ "$output" == *"bad sub cgroup path"* ]]
281281

282282
# Check we can't join non-existing subcgroup.
283283
runc exec --cgroup nonexistent test_busybox cat /proc/self/cgroup
284284
[ "$status" -ne 0 ]
285-
[[ "$output" == *" adding pid "*"/nonexistent/cgroup.procs: no such file "* ]]
285+
[[ "$output" == *" adding pid "*"o such file or directory"* ]]
286286

287287
# Check we can join top-level cgroup (implicit).
288288
runc exec test_busybox grep '^0::/$' /proc/self/cgroup
@@ -318,7 +318,7 @@ function check_exec_debug() {
318318
# Check that --cgroup / disables the init cgroup fallback.
319319
runc exec --cgroup / test_busybox true
320320
[ "$status" -ne 0 ]
321-
[[ "$output" == *" adding pid "*" to cgroups"*"/cgroup.procs: device or resource busy"* ]]
321+
[[ "$output" == *" adding pid "*" to cgroups"*"evice or resource busy"* ]]
322322

323323
# Check that explicit --cgroup foobar works.
324324
runc exec --cgroup foobar test_busybox grep '^0::/foobar$' /proc/self/cgroup

vendor/github.com/coreos/go-systemd/v22/dbus/methods.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/opencontainers/cgroups/cgroups.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/opencontainers/cgroups/fs/fs.go

Lines changed: 26 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/opencontainers/cgroups/fs2/fs2.go

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/opencontainers/cgroups/systemd/common.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)