Skip to content

[1.4] Fix runc exec vs go1.26 + older kernel#5116

Merged
kolyshkin merged 3 commits intoopencontainers:release-1.4from
lifubang:backport-1.4-5091
Feb 12, 2026
Merged

[1.4] Fix runc exec vs go1.26 + older kernel#5116
kolyshkin merged 3 commits intoopencontainers:release-1.4from
lifubang:backport-1.4-5091

Conversation

@lifubang
Copy link
Member

@lifubang lifubang commented Feb 11, 2026

Backport #5091 and #5109

Since PR 4812, runc exec tries to use clone3 syscall with
CLONE_INTO_CGROUP, falling back to the old method if it is not
supported.

One issue with that approach is, a

Cmd cannot be reused after calling its [Cmd.Start], [Cmd.Run],
[Cmd.Output], or [Cmd.CombinedOutput] methods.

(from https://pkg.go.dev/os/exec#Cmd).

This is enforced since Go 1.26, see CL 728642, and so runc exec
actually fails in specific scenarios (go1.26 and no CLONE_INTO_CGROUP
support).

The easiest workaround is to pre-copy the p.cmd structure. From the
CL 734200 it looks like it is an acceptable way. If the upstream
will introduce cmd.Clone we'll switch to it.

As for the test case, it looks like adding Go 1.26 to the testing
matrix is sufficient to reveal the issue (some tests involving
runc exec fail with Go 1.26 before the fix).

@lifubang lifubang added the backport/1.4-pr A backport PR to release-1.4 label Feb 11, 2026
Theoretically, exec.Command can set cmd.Err.

Practically, this should never happen (Linux, Go <= 1.26, exePath is
absolute), but in the unlikely case it does, let's fail early.

This is related to the cloneCmd (to be introduced by the following
commit) which chooses to not copy the Err field. Theoretically,
exec.Command can set Err and so the first call to cmd.Start will fail
(since Err != nil), and the second call to cmd.Start may succeed because
Err == nil. Yet, this scenario is highly unlikely, but better be safe
than sorry.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 82b7597)
Signed-off-by: lifubang <lifubang@acmcoder.com>
Since [PR 4812], runc exec tries to use clone3 syscall with
CLONE_INTO_CGROUP, falling back to the old method if it is not
supported.

One issue with that approach is, a

> Cmd cannot be reused after calling its [Cmd.Start], [Cmd.Run],
> [Cmd.Output], or [Cmd.CombinedOutput] methods.

(from https://pkg.go.dev/os/exec#Cmd).

This is enforced since Go 1.26, see [CL 728642], and so runc exec
actually fails in specific scenarios (go1.26 and no CLONE_INTO_CGROUP
support).

The easiest workaround is to pre-copy the p.cmd structure (copy = *cmd).
From the [CL 734200] it looks like it is an acceptable way, but it might
break in the future as it also copies the private fields, so let's do a
proper field-by-field copy. If the upstream will add cmd.Clone method,
we will switch to it.

Also, we can probably be fine with a post-copy (once the first Start has
failed), but let's be conservative here and do a pre-copy.

[PR 4812]: opencontainers#4812
[CL 728642]: https://go.dev/cl/728642
[CL 734200]: https://go.dev/cl/734200

Reported-by: Efim Verzakov <efimverzakov@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit cb31d62)
Signed-off-by: lifubang <lifubang@acmcoder.com>
Copy link
Member

@rata rata left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Contributor

@kolyshkin kolyshkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lifubang this needs to be a full backport of #5091 + #5109, otherwise the fix is not being tested (no go 1.26).

Feel free to squash the commit from #5109 (ci: bump Go 1.26rc2 -> 1.26.x) into the first commit from #5091, ci: add go 1.26 rc2 (so it would become ci: add go 1.26).

@kolyshkin kolyshkin added this to the 1.4.1 milestone Feb 12, 2026
This commit is a squash of the following two commits:

1. ci: add go 1.26 rc2

This is mostly to test whether https://go.dev/cl/728642 results in
any test failures in the current CI matrix.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit e4e0542)
Signed-off-by: lifubang <lifubang@acmcoder.com>

2. ci: bump Go 1.26rc2 -> 1.26.x

Since Go 1.26.0 is released today.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit daa5ffc)
Signed-off-by: lifubang <lifubang@acmcoder.com>
@lifubang
Copy link
Member Author

@lifubang this needs to be a full backport of #5091 + #5109, otherwise the fix is not being tested (no go 1.26).

Feel free to squash the commit from #5109 (ci: bump Go 1.26rc2 -> 1.26.x) into the first commit from #5091, ci: add go 1.26 rc2 (so it would become ci: add go 1.26).

Haha, I swear I saw this backport happen in a parallel universe where I actually read the PRs before merging. 🥲

Guess I’ll just go ahead and squash it like a time-traveling commit from an alternate reality.

@kolyshkin kolyshkin merged commit 920ca5a into opencontainers:release-1.4 Feb 12, 2026
63 of 64 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport/1.4-pr A backport PR to release-1.4

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants