Commit Graph

7758 Commits

Author SHA1 Message Date
Kir Kolyshkin 920ca5a4e0 Merge pull request #5116 from lifubang/backport-1.4-5091
[1.4] Fix runc exec vs go1.26 + older kernel
2026-02-12 11:58:04 -08:00
lfbzhm 2120bfa4fa Merge pull request #5117 from kolyshkin/1.4-fix-exec
[1.4] libct: prepareCgroupFD: fall back to container init cgroup
2026-02-12 09:53:53 +08:00
Kir Kolyshkin b9e3eec229 ci: add go 1.26
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 e4e05423e4)
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 daa5ffcc84)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2026-02-12 01:26:12 +00:00
Kir Kolyshkin 9ac76a086e tests/int: add "runc exec [init changes cgroup]"
Add a test case to reproduce runc issue 5089.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 1fdbab8107)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-11 12:04:56 -08:00
Kir Kolyshkin 8c8c41675c libct: prepareCgroupFD: fall back to container init cgroup
Previously, when prepareCgroupFD would not open container's cgroup
(as configured in config.json and saved to state.json), it returned
a fatal error, as we presumed a container can't exist without its own
cgroup.

Apparently, it can. In a case when container is configured without
cgroupns (i.e. it uses hosts cgroups), and /sys/fs/cgroup is mounted
read-write, a rootful container's init can move itself to an entirely
different cgroup (even a new one that it just created), and then the
original container cgroup is removed by the kernel (or systemd?) as
it has no processes left. By the way, from the systemd point of view
the container is gone. And yet it is still there, and users want
runc exec to work!

And it worked, thanks to the "let's try container init's cgroup"
fallback as added by commit c91fe9aeba ("cgroup2: exec: join the
cgroup of the init process on EBUSY"). The fallback was added for
the entirely different reason, but it happened to work in this very
case, too.

This behavior was broken with the introduction of CLONE_INTO_CGROUP
support.

While it is debatable whether this is a valid scenario when a container
moves itself into a different cgroup, this very setup is used by e.g.
buildkitd running in a privileged kubernetes container (see issue 5089).

To restore the way things are expected to work, add the same "try
container init's cgroup" fallback into prepareCgroupFD.

While at it, simplify the code flow.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 6c07a37a58)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-11 12:04:56 -08:00
Kir Kolyshkin 404dce8e53 libct: refactor addIntoCgroupV2, fix wrt rootless
1. Refactor addIntoCgroupV2 in an attempt to simplify it.

2. Fix the bug of not trying the init cgroup fallback if
   rootlessCgroup is set. This is a bug because rootlessCgroup
   tells to ignore cgroup join errors, not to never try the fallback.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 1d030fab7d)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-11 12:04:56 -08:00
Kir Kolyshkin 4c530c9551 libct: factor out initProcessCgroupPath
Separate initProcessCgroupPath code out of addIntoCgroupV2.
To be used by the next patch.

While at it, describe the new scenario in which the container's
configured cgroup might not be available.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 94133fab97)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-11 12:04:56 -08:00
Aleksa Sarai 2d4e864979 merge #5114 into opencontainers/runc:release-1.4
Li Fubang (1):
  libct/specconv: fix partial clear of atime mount flags

LGTMs: rata cyphar
2026-02-12 03:29:49 +11:00
Kir Kolyshkin 685bbe04e1 Fix exec vs Go 1.26
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]: https://github.com/opencontainers/runc/pull/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 cb31d62f1c)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2026-02-11 10:23:55 +00:00
Kir Kolyshkin 6a057b84de libct: check cmd.Err after exec.Command call
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 82b7597a26)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2026-02-11 10:23:55 +00:00
lifubang 11a998368c libct/specconv: fix partial clear of atime mount flags
When parsing mount options into recAttrSet and recAttrClr,
the code sets attr_clr to individual atime flags (e.g.
MOUNT_ATTR_NOATIME or MOUNT_ATTR_STRICTATIME) when clearing
atime attributes. However, this violates the kernel's
requirement documented in mount_setattr(2)[1]:

> Note that, since the access-time values are an enumeration
> rather than bit values, a caller wanting to transition to a
> different access-time setting cannot simply specify the
> access-time setting in attr_set, but must also include
> MOUNT_ATTR__ATIME in the attr_clr field.  The kernel will
> verify that MOUNT_ATTR__ATIME isn't partially set in
> attr_clr (i.e., either all bits in the MOUNT_ATTR__ATIME
> bit field are either set or clear), and that attr_set
> doesn't have any access-time bits set if MOUNT_ATTR__ATIME
> isn't set in attr_clr.

Passing only a single atime flag (e.g. MOUNT_ATTR_RELATIME) in
attr_clr causes mount_setattr() to fail with EINVAL.

This change ensures that whenever an atime mode is updated,
attr_clr includes MOUNT_ATTR__ATIME to properly reset the
entire access-time attribute field before applying the new mode.

[1] https://man7.org/linux/man-pages/man2/mount_setattr.2.html

Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit 5560d55bfd)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2026-02-11 10:16:25 +00:00
Akihiro Suda e430416b62 Merge pull request #5110 from kolyshkin/1.4-backports
[1.4] assorted small backports
2026-02-11 14:40:36 +09:00
Kir Kolyshkin 5baeb39534 ci: bump shellcheck to v0.11.0
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 68771cfe51)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Kir Kolyshkin 37281de351 Use Go 1.25 for official builds
(as well as for testing on Cirrus CI)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 79b97d4642)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Kir Kolyshkin 0a743404a9 Bump seccomp to v2.6.0
This version was released almost a year ago.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f4710e5023)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Kir Kolyshkin ba82e372ce ci: bump bats to 1.12.0
This which is already using in CI on Fedora.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f128234354)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Kir Kolyshkin 585724bdaf libct/configs: mark MPOL_* constants as deprecated
Alas, these new constants are already in v1.4.0 release so we can't
remove those right away, but we can mark them as deprecated now
and target removal for v1.5.0.

So,
 - mark them as deprecated;
 - redefine via unix.MPOL_* counterparts;
 - fix the validator code to use unix.MPOL_* directly.

This amends commit a0e809a8.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 3741f9186d)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Aleksa Sarai 4378cb6b8c libct: switch to unix.SetMemPolicy wrapper
This is mostly a mechanical change, but we also need to change some
types to match the "mode int" argument that golang.org/x/sys/unix
decided to use.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit a0e809a8ba)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
dependabot[bot] 1c03887f26 build(deps): bump golang.org/x/sys from 0.37.0 to 0.38.0
Bumps [golang.org/x/sys](https://github.com/golang/sys) from 0.37.0 to 0.38.0.
- [Commits](https://github.com/golang/sys/compare/v0.37.0...v0.38.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sys
  dependency-version: 0.38.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 071beab281)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 14:06:26 -08:00
Kir Kolyshkin 741acec5b7 Enable gofumpt extra rules
Commit b2f8a74d "clothed" the naked return as inflicted by gofumpt
v0.9.0. Since gofumpt v0.9.2 this rule was moved to "extra" category,
not enabled by default. The only other "extra" rule is to group adjacent
parameters with the same type, which also makes sense.

Enable gofumpt "extra" rules, and reformat the code accordingly.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 67840cce4b)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 13:50:38 -08:00
Ariel Otilibili 16885f2d71 libcontainer/seccomp: Use for range over integers
The commit mentioned below has missed these changes.

Fixes: 17570625 ("Use for range over integers")
Signed-off-by: Ariel Otilibili <otilibil@eurecom.fr>
(cherry picked from commit 34da991298)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-02-10 13:50:05 -08:00
lfbzhm 3747639db3 Merge pull request #5094 from kolyshkin/1.4-5093
[1.4] build(deps): bump github.com/coreos/go-systemd/v22 from 22.6.0 to 22.7.0
2026-01-29 18:16:05 +08:00
dependabot[bot] 681385530f build(deps): bump github.com/coreos/go-systemd/v22 from 22.6.0 to 22.7.0
Bumps [github.com/coreos/go-systemd/v22](https://github.com/coreos/go-systemd) from 22.6.0 to 22.7.0.
- [Release notes](https://github.com/coreos/go-systemd/releases)
- [Commits](https://github.com/coreos/go-systemd/compare/v22.6.0...v22.7.0)

---
updated-dependencies:
- dependency-name: github.com/coreos/go-systemd/v22
  dependency-version: 22.7.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
(cherry picked from commit 9abc1824f2)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-01-28 12:08:18 -08:00
Kir Kolyshkin 2a5dff7ea7 internal/systemd: simplify
Remove unused code and argument from the ActivationFiles,
and simplify its usage.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 6ede591761)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-01-28 12:08:06 -08:00
Kir Kolyshkin b0e7359a11 Remove crypto/tls dependency
It appears that when we import github.com/coreos/go-systemd/activation,
it brings in the whole crypto/tls package (which is not used by runc
directly or indirectly), making the runc binary size larger and
potentially creating issues with FIPS compliance.

Let's copy the code of function we use from go-systemd/activation
to avoid that.

The space savings are:

$ size runc.before runc.after
   text	   data	    bss	    dec	    hex	filename
7101084	5049593	 271560	12422237	 bd8c5d	runc.before
6508796	4623281	 229128	11361205	 ad5bb5	runc.after

Reported-by: Dimitri John Ledkov <dimitri.ledkov@surgut.co.uk>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit ba9e60f7a8)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2026-01-28 12:08:06 -08:00
Rodrigo Campos f5a008c439 Merge pull request #5074 from kolyshkin/1.4-5072
[1.4] CI: fix modernize job failure
2025-12-20 01:23:44 -03:00
Kir Kolyshkin 1b249320aa ci: fix modernize URL
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 428043bcf2)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-12-17 12:34:32 -08:00
Kir Kolyshkin a239670e4b ci: drop -test from modernize run
The modernize documentation used to suggest -test flag but it's not
needed as it is enabled by default. Drop it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit dbc4234607)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-12-16 16:52:49 -08:00
Kir Kolyshkin 701561e3f0 ci: use latest Go for modernize job
Since we use modernize@latest, it may require latest Go as well (and now it does),
so use "go-version: stable" explicitly (which resolves to latest Go).

This fixes the issue with CI:

> go: golang.org/x/tools/gopls/internal/analysis/modernize/cmd/modernize@latest: golang.org/x/tools/gopls@v0.21.0 requires go >= 1.25 (running go 1.24.11; GOTOOLCHAIN=local)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 16ee2bbf4c)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-12-16 16:52:41 -08:00
Kir Kolyshkin adf07343cf libc/int: use strings.Builder
Generated by modernize@latest (v0.21.0).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 652269729d)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-12-16 16:52:37 -08:00
Kir Kolyshkin 4e4fd7c9f0 Merge pull request #5062 from loong64/pr-4938-to-release-1.4
[1.4] Add loong64 support in seccomp and PIE
2025-12-15 11:13:03 -08:00
zhaixiaojuan 508d512061 Add loong64 support in seccomp and PIE
Signed-off-by: zhaixiaojuan <zhaixiaojuan@loongson.cn>
(cherry picked from commit 885509afdf)
Signed-off-by: 吴小白 <296015668@qq.com>
2025-12-09 11:15:55 +08:00
Aleksa Sarai fe09117131 merge #5046 into opencontainers/runc:release-1.4
Li Fu Bang (2):
  VERSION: back to development
  VERSION: release 1.4.0

LGTMs: rata cyphar
2025-11-28 10:34:45 +11:00
lifubang ead7182a41 VERSION: back to development
Signed-off-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-28 02:52:35 +11:00
lifubang 8bd78a9977 VERSION: release 1.4.0
Signed-off-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
v1.4.0
2025-11-28 02:52:35 +11:00
Rodrigo Campos 7d84a1282a Merge pull request #5005 from cyphar/1.4-hallucinated-paths
[1.4] pathrs: add "hallucination" helpers for SecureJoin magic
2025-11-27 12:11:12 -03:00
lfbzhm c362d6bd21 Merge pull request #5040 from cyphar/1.4-better-init-errors-4928
[1.4] Better errors from `runc init`
2025-11-27 10:46:29 +08:00
Kir Kolyshkin f1d0dd8fb3 runc create/run/exec: show fatal errors from init
In case early stage of runc init (nsenter) fails for some reason, it
logs error(s) with FATAL log level, via bail().

The runc init log is read by a parent (runc create/run/exec) and is
logged via normal logrus mechanism, which is all fine and dandy, except
when `runc init` fails, we return the error from the parent (which is
usually not too helpful, for example):

	runc run failed: unable to start container process: can't get final child's PID from pipe: EOF

Now, the actual underlying error is from runc init and it was logged
earlier; here's how full runc output looks like:

	FATA[0000] nsexec-1[3247792]: failed to unshare remaining namespaces: No space left on device
	FATA[0000] nsexec-0[3247790]: failed to sync with stage-1: next state
	ERRO[0000] runc run failed: unable to start container process: can't get final child's PID from pipe: EOF

The problem is, upper level runtimes tend to ignore everything except
the last line from runc, and thus error reported by e.g. docker is not
very helpful.

This patch tries to improve the situation by collecting FATAL errors
from runc init and appending those to the error returned (instead of
logging). With it, the above error will look like this:

	ERRO[0000] runc run failed: unable to start container process: can't get final child's PID from pipe: EOF; runc init error(s): nsexec-1[141549]: failed to unshare remaining namespaces: No space left on device; nsexec-0[141547]: failed to sync with stage-1: next state

Yes, it is long and ugly, but at least the upper level runtime will
report it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f944ccecb2)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 17:59:54 -08:00
Kir Kolyshkin 46156624b7 libct/nsenter: better read/write errors
Introduce and use iobail, xread, and xwrite wrappers so that we can
properly check read/write return value and call either bail or bailx on
error, with proper diagnostics (distinguishing failed read/write from a
short read/write).

This prevents the "Success" prefix in errors like:

	failed to sync with stage-1: next state: Success

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 6c18b25cdc)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 17:59:54 -08:00
Kir Kolyshkin c4a61c0227 libct/nsenter: sprinkle missing sane_kill
Add a few missing sane_kill calls where they make sense.

Remove one useless sane_kill of stage2_pid, as during SYNC_USERMAP stage2
is not yet started. It is harmless yet it makes the code slightly harder
to read.

Set the child pid to -1 upon receiving SYNC_CHILD_FINISH
to minimize the chances of killing an unrelated process.
When a child sends SYNC_CHILD_FINISH it is about to exit
(although theoretically it could be stuck during debug logging).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit aea52d0ab0)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 17:59:54 -08:00
Kir Kolyshkin 493f1b10fe libct/nsenter: add and use bailx
We use bail to report fatal errors, and bail always append %m
(aka strerror(errno)). In case an error condition did not set
errno, the log message will end up with ": Success" or an error
from a stale errno value. Either case is confusing for users.

Introduce bailx which is the same as bail except it does not
append %m, and use it where appropriate.

The naming follows libc's err(3) and errx(3).

PS we still use bail in a few cases after read or write, even
if that read/write did not return an error, because the code
does not distinguish between short read/write and error (-1).
This will be addressed by the next commit.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 067b8335e7)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 17:59:54 -08:00
Kir Kolyshkin 7f9fc53c34 libct/nsenter: save errno in sane_kill
Since sane_kill after a failed read or write, but before reporting the
error from that read or write, it may change the errno value in case
kill(2) fails.

Save and restore the errno around the call to kill.

While at it,
 - change the code to return early;
 - don't return kill return value as no one is using it, and the errno
   value no longer correlates.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 9c8f476cb6)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 17:59:54 -08:00
Kir Kolyshkin e18c06bf8e Merge pull request #5041 from lifubang/backport-5014-fd-leaks-flake-1.4
[1.4] libct/int: TestFdLeaks: deflake
2025-11-26 17:57:27 -08:00
Kir Kolyshkin 5bb89872f8 libct/int: TestFdLeaks: deflake
Since the recent CVE fixes, TestFdLeaksSystemd sometimes fails:

	=== RUN   TestFdLeaksSystemd
	    exec_test.go:1750: extra fd 9 -> /12224/task/13831/fd
	    exec_test.go:1753: found 1 extra fds after container.Run
	--- FAIL: TestFdLeaksSystemd (0.10s)

It might have been caused by the change to the test code in commit
ff6fe13 ("utils: use safe procfs for /proc/self/fd loop code") -- we are
now opening a file descriptor during the logic to get a list of file
descriptors. If the file descriptor happens to be allocated to a
different number, you'll get an error.

Let's try to filter out the fd used to read a directory.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 5fbc3bb019)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-11-26 14:11:41 +00:00
lifubang 6a270e49a3 integration: add some tests for bind mount through dangling symlinks
We intentionally broke this in commit d40b3439a9 ("rootfs: switch to
fd-based handling of mountpoint targets") under the assumption that most
users do not need this feature. Sadly it turns out they do, and so
commit 3f925525b4 ("rootfs: re-allow dangling symlinks in mount
targets") added a hotfix to re-add this functionality.

This patch adds some much-needed tests for this behaviour, since it
seems we are going to need to keep this for compatibility reasons (at
least until runc v2...).

Co-developed-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 15d7c214cd)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:38 +11:00
Aleksa Sarai aa3be89f0d pathrs: add MkdirAllParentInRoot helper
While CreateInRoot supports hallucinating the target path, we do not use
it directly when constructing device inode targets because we need to
have different handling for mknod and bind-mounts.

The solution is to simply have a more generic MkdirAllParentInRoot
helper that MkdirAll's the parent directory of the target path and then
allows the caller to create the trailing component however they like.
(This can be used by CreateInRoot internally as well!)

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 195e9551e4)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:38 +11:00
Aleksa Sarai da73ade8da pathrs: add "hallucination" helpers for SecureJoin magic
In order to maintain compatibility with previous releases of runc (which
permitted dangling symlinks as path components by permitting
non-existent path components to be treated like real directories) we
have to first do SecureJoin to construct a target path that is
compatible with the old behaviour but has all dangling symlinks (or
other invalid paths like ".." components after non-existent directories)
removed.

This is effectively a more generic verison of commit 3f925525b4
("rootfs: re-allow dangling symlinks in mount targets") and will let us
remove the need for open-coding SecureJoin workarounds.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit cfb74326be)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:38 +11:00
Aleksa Sarai 7bf92b9d6a pathrs: rename MkdirAllInRootOpen -> MkdirAllInRoot
Now that MkdirAllInRoot has been removed, we can make MkdirAllInRootOpen
less wordy by renaming it to MkdirAllInRoot. This is a non-functional
change.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 20c5a8ec4a)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:37 +11:00
Aleksa Sarai c2bde92ce8 libct: switch final WithProcfd users to WithProcfdFile
This probably should've been done as part of commit d40b3439a9
("rootfs: switch to fd-based handling of mountpoint targets") but it
seems I missed them when doing the rest of the conversions.

This also lets us remove utils.WithProcfd entirely, as well as
pathrs.MkdirAllInRoot. Unfortunately, WithProcfd was exposed in the
externally-importable "libcontainer/utils" package and so we need to
have a deprecation notice to remove it in runc 1.5.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 9dbd37e06f)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:37 +11:00
Aleksa Sarai 50aa47ba69 libcontainer: move CleanPath and StripRoot to internal/pathrs
These helpers will be needed for the compatibility code added in future
patches in this series, but because "internal/pathrs" is imported by
"libcontainer/utils" we need to move them so that we can avoid circular
dependencies.

Because the old functions were in a non-internal package it is possible
some downstreams use them, so add some wrappers but mark them as
deprecated.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 42a1e19d67)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-26 21:05:37 +11:00