This is a follow-up to #5275. That change reused a single tmpfs mount
to mask multiple directories, which is efficient when masking more than
one path. However, it introduced unnecessary overhead when only one
directory is masked. This commit restores the original behavior for the
single-path case while preserving shared tmpfs logic for multiple paths.
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit e7e2f00248)
Signed-off-by: lifubang <lifubang@acmcoder.com>
Kubernetes may add one sysfs thermal_throttle entry per CPU to
maskedPaths. On large Intel systems this can produce many directory
masks for a single container. runc currently handles each directory
mask with a separate read-only tmpfs mount, and therefore a separate
tmpfs superblock.
On Linux 4.18/RHEL 8 kernels, creating and tearing down many tmpfs
superblocks can contend on the global shrinker_rwsem when containers
start or stop concurrently.
Use one read-only tmpfs for directory masks and bind-mount it over the
remaining directory targets. The first non-procfs-fd directory mount is
reopened through the container root fd before it is reused. File masks
still bind /dev/null, and procfs fd targets keep the existing
one-tmpfs-per-target behaviour because they are fd aliases rather than
stable rootfs paths.
If the bind-mount of the shared source fails (e.g. due to kernel
restrictions), fall back to individual tmpfs mounts for all remaining
directories. Tmpfs mounts use nr_blocks=1,nr_inodes=1 to minimise
kernel resource usage.
The bind mounts do not create additional tmpfs superblocks. They also
retain the read-only mount flag inherited from the source vfsmount, so
the masking semantics remain unchanged.
xref: kubernetes/kubernetes#138512
xref: kubernetes/kubernetes#138388
xref: kubernetes/kubernetes#131018
Co-authored-by: Davanum Srinivas <davanum@gmail.com>
Refactored-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit c046c9b973)
Signed-off-by: lifubang <lifubang@acmcoder.com>
Previously, masked directories (e.g., /proc/acpi, /proc/scsi) were
mounted as read-only tmpfs without explicit size or inode limits.
Although these mounts are meant to be empty and unwritable, the lack
of resource constraints means that—should an attacker bypass the
read-only protection (e.g., via container escape, mount namespace
manipulation, or a kernel vulnerability)—the tmpfs could consume up
to 50% of system memory by default (the kernel's default tmpfs limit).
To mitigate this risk in high-density container environments and
adhere to the principle of least privilege, we now explicitly set:
- nr_blocks=1 (sufficient for at most one block size)
- nr_inodes=1 (sufficient for at most one inode)
Ref: https://man7.org/linux/man-pages/man5/tmpfs.5.html
These limits ensure that even if compromised, kernel memory usage
remains strictly bounded and negligible.
This change aligns with best practices used by other container
runtimes and strengthens defense-in-depth for sensitive masked paths.
Co-authored-by: Davanum Srinivas <davanum@gmail.com>
Refactored-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit e57a7a4c8f)
Signed-off-by: lifubang <lifubang@acmcoder.com>
When RUNC_USE_SYSTEMD is set, tests/rootless.sh is using
ssh -tt rootless@localhost
to run tests as rootless user. In this case, local environment is not
passed to the user's ssh session (unless explicitly specified), and so
the tests do not get ROOTLESS_FEATURES.
As a result, idmap-related tests are skipped when running as rootless
using systemd cgroup driver:
integration test (systemd driver)
...
[02] run rootless tests ... (idmap)
...
ok 286 runc run detached ({u,g}id != 0) # skip test requires rootless_idmap
...
Fix this by creating a list of environment variables needed by the
tests, and adding those to ssh command line (in case of ssh) or
exporting (in case of sudo) so both cases work similarly.
Also, modify disable_idmap to unset variables set in enable_idmap so
they are not exported at all if idmap is not in features.
Fixes: bf15cc99 ("cgroup v2: support rootless systemd")
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 3e0829d195)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
When signal installation was moved to a goroutine for performance,
containers that exited quickly could complete before SIGCHLD was
registered, causing runc to hang waiting for the signal.
This fix ensures SIGCHLD is registered immediately in the main thread
before other signals are handled in the goroutine, maintaining performance
while guaranteeing no missed SIGCHLD notifications for fast-exiting
containers.
Reported-by: Ayato Tokubi <atokubi@redhat.com>
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit 404181e4cc)
Signed-off-by: lifubang <lifubang@acmcoder.com>
This adds a CI job to run conmon tests with runc.
Related to issue 5151, PR 5153.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 192e3d416f)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This fixes random failures to start a container in conmon integration
tests (see issue 5151).
I guess we need to find another way to fix issue 4645.
This reverts commit 1b39997e73.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 5996fe143a)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Some maintainers appear to have removed their PGP keys, which causes
"gpg --import" during "make validate-keyring" to fail. The solution is
to switch to a non-fatal warning if no keys were imported.
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 936a59b07f)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
I no longer work at SUSE and thus this key (and email address) are no
longer associated with me.
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit a691486c83)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
SCMP_ACT_KILL terminates the process with a fatal signal, which may
produce a core dump depending on the host configuration.
While this is harmless on ephemeral CI instances, it can leave unwanted
core files on developer or customer systems. It also interferes with
test environments that detect unexpected core dumps.
Signed-off-by: Ricardo Branco <rbranco@suse.de>
(cherry picked from commit f18e97d312)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
When container-selinux 4:2.246.0-1.el10 is installed, it produces the
following %post script warnings:
> ...
> Running scriptlet: container-selinux-4:2.246.0-1.el10.noarch 26/37
> Installing : container-selinux-4:2.246.0-1.el10.noarch 26/37
> Running scriptlet: container-selinux-4:2.246.0-1.el10.noarch 26/37
> libsemanage.semanage_pipe_data: Child process /usr/libexec/selinux/hll/pp failed with code: 255. (No data available).
> libsemanage.semanage_compile_module: container: libsepol.policydb_read: policydb module version 24 does not match my version range 4-23.
> libsemanage.semanage_compile_module: container: libsepol.sepol_module_package_read: invalid module in module package (at section 0).
> libsemanage.semanage_compile_module: container: libsepol.sepol_ppfile_to_module_package: Failed to read policy package.
> libsemanage.semanage_direct_commit: Failed to compile hll files into cil files. (No data available).
> semodule: Failed!
> ...
For some reason, dnf install still succeeds, but when the selinux tests
fail with:
> chcon: failed to change context of '/tmp/bats-run-3MMyYP/runc.szTqBc/bundle/runc' to ‘system_u:object_r:container_runtime_exec_t:s0’: Invalid argument
All this is fixed once policycoreutils is added to the list of RPMS so
it is updated (from 3.9-3.el10 to 3.10-1.el10) during the same
transaction.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 3235c5a90a)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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>
Go 1.24 is no longer supported, and Go 1.25 (which we use in Dockerfile
for official binaries) is not being tested against.
So remove Go 1.24.x and add Go 1.25.x.
We keep Go 1.23.x is this is a minimally required version for this
branch.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Bump bats to the version from Fedora 42 (used in "fedora" job), so we
have the same version everywhere.
This also fixes an issue introduced by commit d31e6b87 (which forgot to
bump bats in GHA CI), and adds a note to the yaml in order to avoid the
same issue in the future.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 6af1d637ba)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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>
The dependency was initially slated for an upgrade from v0.6.0 to v0.6.1
to address an fd leak. However, due to compatibility constraints, we
instead downgrade to v0.5, using v0.5.2 which includes a backported fix
for the same issue.
Signed-off-by: lifubang <lifubang@acmcoder.com>