Commit Graph

2912 Commits

Author SHA1 Message Date
Kir Kolyshkin 3755b0e48c Revert "Preventing containers from being unable to be deleted"
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>
2026-03-09 17:26:27 -07:00
lifubang bb7d09e63e 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:18:18 +00:00
Kir Kolyshkin e1a6adc946 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:14:27 +00:00
lifubang 52192a8e24 libct: add a defer fd close in createDeviceNode
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit 9a5e6262f0bf4e3e654b1a0d71bb804093948f85)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-11-20 11:52:35 +00:00
lifubang 98dc593f13 libct: always close m.dstFile in mountToRootfs
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit e0272886047915899ec06e06665723fc453d3cbf)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-11-20 11:52:35 +00:00
Aleksa Sarai daf9664eb4 rootfs: only set mode= for tmpfs mount if target already existed
This was always the intended behaviour but commit 72fbb34f50 ("rootfs:
switch to fd-based handling of mountpoint targets") regressed it when
adding a mechanism to create a file handle to the target if it didn't
already exist (causing the later stat to always succeed).

A lot of people depend on this functionality, so add some tests to make
sure we don't break it in the future.

Fixes: 72fbb34f50 ("rootfs: switch to fd-based handling of mountpoint targets")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 9a9719eeb4)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-11 03:11:53 +11:00
Kir Kolyshkin 9381215c1f libct: fix mips compilation
On MIPS arches, Rdev is uint32 so we have to convert it.

Fixes issue 4962.

Fixes: 8476df83 ("libct: add/use isDevNull, verifyDevNull")
Fixes: de87203e ("console: verify /dev/pts/ptmx before use")
Fixes: 398955bc ("console: add fallback for pre-TIOCGPTPEER kernels")
Reported-by: Tianon Gravi <admwiggin@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 1b954f1f06)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-06 13:46:38 +11:00
Aleksa Sarai b370bafce9 merge private security patches into ghsa-release-1.3.3
Aleksa Sarai (22):
  rootfs: re-allow dangling symlinks in mount targets
  openat2: improve resilience on busy systems
  selinux: use safe procfs API for labels
  rootfs: switch to fd-based handling of mountpoint targets
  libct/system: use securejoin for /proc/$pid/stat
  init: use securejoin for /proc/self/setgroups
  init: write sysctls using safe procfs API
  utils: remove unneeded EnsureProcHandle
  utils: use safe procfs for /proc/self/fd loop code
  apparmor: use safe procfs API for labels
  ci: add lint to forbid the usage of os.Create
  rootfs: avoid using os.Create for new device inodes
  internal: add wrappers for securejoin.Proc*
  go.mod: update to github.com/cyphar/filepath-securejoin@v0.5.0
  console: verify /dev/pts/ptmx before use
  console: avoid trivial symlink attacks for /dev/console
  console: add fallback for pre-TIOCGPTPEER kernels
  console: use TIOCGPTPEER when allocating peer PTY
  *: switch to safer securejoin.Reopen
  internal: move utils.MkdirAllInRoot to internal/pathrs
  internal/sys: add VerifyInode helper
  internal: linux: add package doc-comment

Li Fubang (1):
  libct: align param type for mountCgroupV1/V2 functions

Kir Kolyshkin (3):
  libct: maskPaths: don't rely on ENOTDIR for mount
  libct: maskPaths: only ignore ENOENT on mount dest
  libct: add/use isDevNull, verifyDevNull

Fixes: CVE-2025-31133 GHSA-9493-h29p-rfm2
Fixes: CVE-2025-52565 GHSA-qw9x-cqr3-wc7r
Fixes: CVE-2025-52881 GHSA-cgrx-mc8f-2prm
Reported-by: Lei Wang <ssst0n3@gmail.com>
Reported-by: Li Fubang <lifubang@acmcoder.com>
Reported-by: Tõnis Tiigi <tonistiigi@gmail.com>
Reported-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-05 20:05:20 +11:00
Aleksa Sarai 4edba17619 rootfs: re-allow dangling symlinks in mount targets
It seems there are a fair few images where dangling symlinks are used as
path components for mount targets, which pathrs-lite does not support
(and it would be difficult to fully support this in a race-free way).

This was actually meant to be blocked by commit 63c2908164 ("rootfs:
try to scope MkdirAll to stay inside the rootfs"), followed by commit
dd827f7b71 ("utils: switch to securejoin.MkdirAllHandle"). However, we
still used SecureJoin to construct mountpoint targets, which means that
dangling symlinks were "resolved" before reaching pathrs-lite.

This patch basically re-adds this hack in order to reduce the breakages
we've seen so far.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-11-05 19:55:06 +11:00
Kir Kolyshkin 72e673cf13 all: format sources with gofumpt v0.9.1
Since gofumpt v0.9.0 there's a new formatting rule to "clothe" any naked
returns.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit b2f8a74de5)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-10-16 04:55:08 +00:00
Aleksa Sarai 72fbb34f50 rootfs: switch to fd-based handling of mountpoint targets
An attacker could race with us during mount configuration in order to
trick us into mounting over an unexpected path. This would bypass
checkProcMount() and would allow for security profiles to be left
unapplied by mounting over /proc/self/attr/... (or even more serious
outcomes such as killing the entire system by tricking runc into writing
strings to /proc/sysrq-trigger).

This is a larger issue with our current mount infrastructure, and the
ideal solution would be to rewrite it all to be fd-based (which would
also allow us to support the "new" mount API, which also avoids a bunch
of other issues with mount(8)). However, such a rewrite is not really
workable as a security fix, so this patch is a bit of a compromise
approach to fix the issue while also moving us a bit towards that
eventual end-goal.

The core issue in CVE-2025-52881 is that we currently use the (insecure)
SecureJoin to re-resolve mountpoint target paths multiple times during
mounting. Rather than generating a string from createMountpoint(), we
instead open an *os.File handle to the target mountpoint directly and
then operate on that handle. This will make it easier to remove
utils.WithProcfd() and rework mountViaFds() in the future.

The only real issue we need to work around is that we need to re-open
the mount target after doing the mount in order to get a handle to the
mountpoint -- pathrs.Reopen() doesn't work in this case (it just
re-opens the inode under the mountpoint) so we need to do a naive
re-open using the full path. Note that if we used move_mount(2) this
wouldn't be a problem because we would have a handle to the mountpoint
itself.

Note that this is still somewhat of a temporary solution -- ideally
mountViaFds would use *os.File directly to let us avoid some other
issues with using bare /proc/... paths, as well as also letting us more
easily use the new mount API on modern kernels.

Fixes: GHSA-cgrx-mc8f-2prm CVE-2025-52881
Co-developed-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:34 +11:00
lifubang 707c4b03c5 libct: align param type for mountCgroupV1/V2 functions
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-10-16 11:29:34 +11:00
Aleksa Sarai 9df8180e0c libct/system: use securejoin for /proc/$pid/stat
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:34 +11:00
Aleksa Sarai 7762edc82c init: use securejoin for /proc/self/setgroups
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:34 +11:00
Aleksa Sarai c77ade57c9 init: write sysctls using safe procfs API
sysctls could in principle also be used as a write gadget for arbitrary
procfs files. As this requires getting a non-subset=pid /proc handle we
amortise this by only allocating a single procfs handle for all sysctl
writes.

Fixes: GHSA-cgrx-mc8f-2prm CVE-2025-52881
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:34 +11:00
Aleksa Sarai 3cdcddff03 utils: remove unneeded EnsureProcHandle
All of the callers of EnsureProcHandle now use filepath-securejoin's
ProcThreadSelf to get a file handle, which has much stricter
verification to avoid procfs attacks than EnsureProcHandle's very
simplistic filesystem type check.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:33 +11:00
Aleksa Sarai 2494b91604 utils: use safe procfs for /proc/self/fd loop code
From a safety perspective this might not be strictly required, but it
paves the way for us to remove utils.ProcThreadSelf.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:33 +11:00
Aleksa Sarai d1c47106d9 apparmor: use safe procfs API for labels
EnsureProcHandle only protects us against a tmpfs mount, but the risk of
a procfs path being used (such as /proc/self/sched) has been known for a
while. Now that filepath-securejoin has a reasonably safe procfs API,
switch to it.

Fixes: GHSA-cgrx-mc8f-2prm CVE-2025-52881
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:33 +11:00
Aleksa Sarai af11e85a38 ci: add lint to forbid the usage of os.Create
os.Create is shorthand for open(O_CREAT|O_TRUNC) *without* O_EXCL, which
is incredibly unsafe for us to do when interacting with a container
rootfs (especially before pivot_root) as an attacker could swap the
target path with a symlink that points to the host filesystem, causing
us to delete the contents of or create host files.

We did have a similar bug in CVE-2024-45310, but in that case we
(luckily) didn't have O_TRUNC set which avoided the worst possible case.
However, os.Create does set O_TRUNC and we were using it in scenarios
that may have been exploitable.

Because of how easy it us for us to accidentally introduce this kind of
bug, we should simply not allow the usage of os.Create in our entire
codebase.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:33 +11:00
Aleksa Sarai f4f8e8db05 rootfs: avoid using os.Create for new device inodes
If an attacker were to make the target of a device inode creation be a
symlink to some host path, os.Create would happily truncate the target
which could lead to all sorts of issues. This exploit is probably not as
exploitable because device inodes are usually only bind-mounted for
rootless containers, which cannot overwrite important host files (though
user files would still be up for grabs).

The regular inode creation logic could also theoretically be tricked
into changing the access mode and ownership of host files if the
newly-created device inode was swapped with a symlink to a host path.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:33 +11:00
Aleksa Sarai e34a0a0936 console: verify /dev/pts/ptmx before use
This is primarily done out of an abudance of caution against runc exec
being attacked by a container where /dev/pts/ptmx has been replaced with
some other bad inode (a disconnected NFS handle, a symlink that goes
through a leaked runc file descriptor to reference a host ptmx, etc).

Unfortunately, we cannot trivially verify that /dev/pts/ptmx is actually
the /dev/pts from the container without storing stuff like the fsid in
the runc state.json, which is probably not worth the extra effort. This
should at least avoid the most concerning cases.

Reported-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:32 +11:00
Aleksa Sarai c3f8ba303e console: avoid trivial symlink attacks for /dev/console
An attacker could make /dev/console a symlink. This presents two
possible issues:

 1. os.Create will happily truncate targets, which could have resulted
    in a worse version of CVE-2024-4531. Luckily, this all happens after
    pivot_root(2) so the scope of that particular attack is fairly
    limited (you are unlikely to be able to easily access host rootfs
    files -- though it might be possible to take advantage of leaks such
    as in CVE-2024-21626). However, O_CREAT|O_NOFOLLOW is what we should
    be doing for all file creations.

 2. Because we passed /dev/console as the only mount path (as opposed to
    using a /proc/self/fd/$n path), an attacker could swap the symlink
    to point to any other path and thus cause us to mount over some
    other path. This is not as big of a problem because all the mounts
    are in the container namespace after pivot_root(2), and users
    usually can create arbitrary mount targets inside the container.

These issues don't seem particularly exploitable, but they deserve to be
hardened regardless.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:32 +11:00
Aleksa Sarai a45564c23e console: add fallback for pre-TIOCGPTPEER kernels
The pty driver has very consistent allocation rules for the major:minor
numbers of /dev/pts/$n inodes, so it is possible to somewhat safely open
/dev/pts/* paths if we validate that the inode is the one we expect.

It is possible for an attacker to have over-mounted a pts peer from a
different devpts instance, but to fix this would require more tracking
of devpts instances than runc currently can do.

This means runc should continue to work on very old kernels.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:32 +11:00
Aleksa Sarai 68b07ce127 console: use TIOCGPTPEER when allocating peer PTY
When opening the peer end of a pty, the old kernel API required us to
open /dev/pts/$num inside the container (at least since we fixed console
handling many years ago in commit 244c9fc426 ("*: console rewrite")).

The problem is that in a hostile container it is possible for
/dev/pts/$num to be an attacker-controlled symlink that runc can be
tricked into resolving when doing bind-mounts. This allows the attacker
to (among other things) persist /proc/... entries that are later masked
by runc, allowing an attacker to escape through the kernel.core_pattern
sysctl (/proc/sys/kernel/core_pattern). This is the original issue
reported by Lei Wang and Li Fu Bang in CVE-2025-52565.

However, it should be noted that this is not entirely a newly-discovered
problem. Way back in Linux 4.13 (2017), I added the TIOCGPTPEER ioctl,
which allows us to get a pty peer without touching the /dev/pts inside
the container. The original threat model was around an attacker
replacing /dev/pts/$n or /dev/pts/ptmx with some malicious inode (a DoS
inode, or possibly a PTY they wanted a confused deputy to operate on).
Unfortunately, there was no practical way for runc to cache a safe
O_PATH handle to /dev/pts/ptmx (unlike other runtimes like LXC, which
switched to TIOCGPTPEER way back in 2017). Since it wasn't clear how we
could protect against the main attack TIOCGPTPEER was meant to protect
against, we never switched to it (even though I implemented it
specifically to harden container runtimes).

Unfortunately, It turns out that mount *sources* are a threat we didn't
fully consider. Since TIOCGPTPEER already solves this problem entirely
for us in a race free way, we should just use that. In a later patch, we
will add some hardening for /dev/pts/$num opening to maintain support
for very old kernels (Linux 4.13 is very old at this point, but RHEL 7
is still kicking and is stuck on Linux 3.10).

Fixes: GHSA-qw9x-cqr3-wc7r CVE-2025-52565
Reported-by: Lei Wang <ssst0n3@gmail.com> (CVE-2025-52565)
Reported-by: lfbzhm <lifubang@acmcoder.com> (CVE-2025-52565)
Reported-by: Aleksa Sarai <cyphar@cyphar.com> (TIOCGPTPEER)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:31 +11:00
Kir Kolyshkin 73d4be0f1b libct: maskPaths: don't rely on ENOTDIR for mount
Currently, we rely on mount returning ENOTDIR when the destination is a
directory (and so mount tells us that the source is not), and fall back
to read-only tmpfs bind mount for such cases.

Theoretically, ENOTDIR can also be returned in some other cases,
resulting in the wrong type of mount being used.

Let's be more straightforward here -- call fstat on destination file
descriptor, and use the proper mount depending on whether it is a
directory.

Reported-by: Rodrigo Campos <rodrigoca@microsoft.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-10-16 11:29:31 +11:00
Kir Kolyshkin b3bee13bfc libct: maskPaths: only ignore ENOENT on mount dest
When mounting a path being masked, the /dev/null might disappear from
under us, and mount (even on an opened /dev/null file descriptor) will
return ENOENT, which we deliberately ignore, as there's no need to mask
non-existent paths.

Let's open the destination path and ignore ENOENT during open, then
mount via the destination file descriptor, not ignoring ENOENT.

Reported-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-10-16 11:29:31 +11:00
Kir Kolyshkin 71a4324fc3 libct: add/use isDevNull, verifyDevNull
The /dev/null in a container should not be trusted, because when /dev
is a bind mount, /dev/null is not created by runc itself.

1. Add isDevNull which checks the fd minor/major and device type,
   and verifyDevNull which does the stat and the check.

2. Rewrite maskPath to open and check /dev/null, and use its fd to
   perform mounts. Move the loop over the MaskPaths into the function,
   and rename it to maskPaths.

3. reOpenDevNull: use verifyDevNull and isDevNull.

4. fixStdioPermissions: use isDevNull instead of stat.

Fixes: GHSA-9493-h29p-rfm2 CVE-2025-31133
Co-authored-by: Rodrigo Campos <rodrigoca@microsoft.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:31 +11:00
Aleksa Sarai 345a66c7a1 *: switch to safer securejoin.Reopen
filepath-securejoin v0.3 gave us a much safer re-open primitive, we
should use it to avoid any theoretical attacks. Rather than using it
direcly, add a small pathrs wrapper to make libpathrs migrations in the
future easier...

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:31 +11:00
Aleksa Sarai d540e01c9b internal: move utils.MkdirAllInRoot to internal/pathrs
We will have more wrappers around filepath-securejoin, and so move them
to their own specific package so that we can eventually use libpathrs
fairly cleanly (by swapping out the implementation).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-10-16 11:29:30 +11:00
Kir Kolyshkin e34f6438e9 libct: State: ensure Resources is not nil
Since opencontainers/cgroups v0.0.2 (commit b206a015), all stuct
Resources fields are annotated with "omitempty" attribute.
As a result, the loaded configuration may have Resources == nil.

It is totally OK (rootless containers may have no resources configured)
except since commit 6c5441e5, cgroup v1 fs manager requires Resources to
be set in the call to NewManager (this is a cgroup v1 deficiency,
or maybe our implementation deficiency, or both).

To work around this, let's add code to ensure Resources is never nil
after loading from state.json.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-09-23 13:11:53 -04:00
Kir Kolyshkin 02c4128288 criu: simplify isOnTmpfs check in prepareCriuRestoreMounts
Instead of generating a list of tmpfs mount and have a special function
to check whether the path is in the list, let's go over the list of
mounts directly. This simplifies the code and improves readability.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit ce3cd4234c)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-08-28 12:28:32 +08:00
Kir Kolyshkin 69a3439c31 criu: inline makeCriuRestoreMountpoints
Since its code is now trivial, and it is only called from a single
place, it does not make sense to have it as a separate function.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit f91fbd34d9)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-08-28 12:28:32 +08:00
Kir Kolyshkin a97c49f96e criu: ignore cgroup early in prepareCriuRestoreMounts
It makes sense to ignore cgroup mounts much early in the code,
saving some time on unnecessary operations.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit b8aa5481db)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-08-28 12:28:32 +08:00
Kir Kolyshkin 017d6b693f criu: improve prepareCriuRestoreMounts
1. Replace the big "if !" block with the if block and continue,
   simplifying the code flow.

2. Move comments closer to the code, improving readability.

This commit is best reviewed with --ignore-all-space or similar.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 0c93d41c65)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-08-28 12:28:32 +08:00
Aleksa Sarai 9a79ff4793 [1.3] libct: reset CPU affinity by default
In certain deployments, it's possible for runc to be spawned by a
process with a restrictive cpumask (such as from a systemd unit with
CPUAffinity=... configured) which will be inherited by runc and thus the
container process by default.

The cpuset cgroup used to reconfigure the cpumask automatically for
joining processes, but kcommit da019032819a ("sched: Enforce user
requested affinity") changed this behaviour in Linux 6.2.

The solution is to try to emulate the expected behaviour by resetting
our cpumask to correspond with the configured cpuset (in the case of
"runc exec", if the user did not configure an alternative one). Normally
we would have to parse /proc/stat and /sys/fs/cgroup, but luckily
sched_setaffinity(2) will transparently convert an all-set cpumask (even
if it has more entries than the number of CPUs on the system) to the
correct value for our usecase.

For some reason, in our CI it seems that rootless --systemd-cgroup
results in the cpuset (presumably temporarily?) being configured such
that sched_setaffinity(2) will allow the full set of CPUs. For this
particular case, all we care about is that it is different to the
original set, so include some special-casing (but we should probably
investigate this further...).

Reported-by: ningmingxiao <ning.mingxiao@zte.com.cn>
Reported-by: Martin Sivak <msivak@redhat.com>
Reported-by: Peter Hunt <pehunt@redhat.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(Cherry-pick of commit 121192ade6c55f949d32ba486219e2b1d86898b2.)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-08-28 10:57:05 +10:00
Aleksa Sarai 3ac9e16562 [1.3] rootfs: remove /proc/net/dev from allowed overmount list
This was added in 2ee9cbbd12 ("It's /proc/stat, not /proc/stats") with
no actual justification, and doesn't really make much sense on further
inspection:

 * /proc/net is a symlink to "self/net", which means that /proc/net/dev
   is a per-process file, and so overmounting it would only affect pid1.
   Any other program that cares about /proc/net/dev would see their own
   process's configuration, and unprivileged processes wouldn't be able
   to see /proc/1/... data anyway.

   In addition, the fact that this is a symlink means that runc will
   deny the overmount because /proc/1/net/dev is not in the proc
   overmount allowlist. This means that this has not worked for many
   years, and probably never worked in the first place.

 * /proc/self/net is already namespaced with network namespaces, so the
   primary argument for allowing /proc overmounts (lxcfs-like masking of
   procfs files to emulate namespacing for files that are not properly
   namespaced for containers -- such as /proc/cpuinfo) is moot.

   It goes without saying that lxcfs has never overmounted
   /proc/self/net/... files, so the general "because lxcfs"
   justification doesn't hold water either.

 * The kernel has slowly been moving towards blocking overmounts in
   /proc/self/. Linux 6.12 blocked overmounts for fd, fdinfo, and
   map_files; future Linux versions will probably end up blocking
   everything under /proc/self/.

Fixes: 2ee9cbbd12 ("It's /proc/stat, not /proc/stats")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry-picked from commit 3620185d06b79da836559b75161027c6273fff7b.)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-07-25 19:18:06 +10:00
Pavel Liubimov ce4ad9922b libcontainer: close seccomp agent connection to prevent resource leaks
Add missing defer conn.Close().

Signed-off-by: Pavel Liubimov <prlyubimov@gmail.com>
(cherry picked from commit aa0e7989c4)
Signed-off-by: Pavel Liubimov <prlyubimov@gmail.com>
2025-07-04 00:04:53 +03:00
HirazawaUi 2ff7959434 Preventing containers from being unable to be deleted
Signed-off-by: HirazawaUi <695097494plus@gmail.com>
(cherry picked from commit e5a74679b32b32a7670f2a19c99974d96f1585a8)
Signed-off-by: HirazawaUi <695097494plus@gmail.com>
2025-06-22 22:32:06 +08:00
Yusuke Sakurai c682547894 fix rootfs propagation mode
Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com>
(cherry picked from commit 04be81b6a3)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-06-20 16:52:01 +08:00
Kir Kolyshkin 15dc7b516e libct/configs: stop using deprecated id
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit d22a42113d)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-06-19 10:37:52 -07:00
Kir Kolyshkin af614c94bd libct/configs: fix/improve deprecation notices
The per-file deprecation in cgroup_deprecated.go is not working,
let's replace it.

Link to Hooks.Run in Hook.Run deprecation notice.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit b25bcaa8b3)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-06-19 10:35:21 -07:00
Kir Kolyshkin daada5e850 libct/configs: add package docstring
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit a10d338eb2)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-06-19 10:35:21 -07:00
Kir Kolyshkin 6a39b49150 libct/intelrdt: fix staticcheck ST1020 warnings
> libcontainer/intelrdt/cmt.go:5:1: ST1020: comment on exported function IsCMTEnabled should be of the form "IsCMTEnabled ..." (staticcheck)
> // Check if Intel RDT/CMT is enabled.
> ^
> libcontainer/intelrdt/intelrdt.go:419:1: ST1020: comment on exported function IsCATEnabled should be of the form "IsCATEnabled ..." (staticcheck)
> // Check if Intel RDT/CAT is enabled
> ^
> libcontainer/intelrdt/intelrdt.go:425:1: ST1020: comment on exported function IsMBAEnabled should be of the form "IsMBAEnabled ..." (staticcheck)
> // Check if Intel RDT/MBA is enabled
> ^
> libcontainer/intelrdt/intelrdt.go:446:1: ST1020: comment on exported method Apply should be of the form "Apply ..." (staticcheck)
> // Applies Intel RDT configuration to the process with the specified pid
> ^
> libcontainer/intelrdt/intelrdt.go:481:1: ST1020: comment on exported method Destroy should be of the form "Destroy ..." (staticcheck)
> // Destroys the Intel RDT container-specific 'container_id' group
> ^
> libcontainer/intelrdt/intelrdt.go:497:1: ST1020: comment on exported method GetPath should be of the form "GetPath ..." (staticcheck)
> // Returns Intel RDT path to save in a state file and to be able to
> ^
> libcontainer/intelrdt/intelrdt.go:506:1: ST1020: comment on exported method GetStats should be of the form "GetStats ..." (staticcheck)
> // Returns statistics for Intel RDT
> ^
> libcontainer/intelrdt/mbm.go:6:1: ST1020: comment on exported function IsMBMEnabled should be of the form "IsMBMEnabled ..." (staticcheck)
> // Check if Intel RDT/MBM is enabled.
> ^
> 8 issues:
> * staticcheck: 8

While at it, add missing periods.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 9b3ccc19a6)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-04-24 02:35:52 +00:00
Kir Kolyshkin 1ceca3718b Fix staticcheck ST1020/ST1021 warnings
I was pretty sure we have a linter for these but apparently we did not.

> libcontainer/capabilities/capabilities.go:108:1: ST1020: comment on exported method ApplyCaps should be of the form "ApplyCaps ..." (staticcheck)
> // Apply sets all the capabilities for the current process in the config.
> ^
>
>
> types/events.go:15:1: ST1021: comment on exported type Stats should be of the form "Stats ..." (with optional leading article) (staticcheck)
> // stats is the runc specific stats structure for stability when encoding and decoding stats.
> ^

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 30f8acabf6)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-04-24 02:35:52 +00:00
Kir Kolyshkin 5d9653d8f7 Fix a few staticcheck QF1001 warnings
Like these:

> libcontainer/criu_linux.go:959:3: QF1001: could apply De Morgan's law (staticcheck)
> 		!(req.GetType() == criurpc.CriuReqType_FEATURE_CHECK ||
> 		^
> libcontainer/rootfs_linux.go:360:19: QF1001: could apply De Morgan's law (staticcheck)
> 	if err == nil || !(errors.Is(err, unix.EPERM) || errors.Is(err, unix.EBUSY)) {
> 	                 ^

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 9510ffb658)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-04-24 02:35:52 +00:00
Kir Kolyshkin bd84d8a37a libct: fix staticcheck QF1006 warning
> libcontainer/rootfs_linux.go:1255:13: QF1004: could use strings.ReplaceAll instead (staticcheck)
> 	keyPath := strings.Replace(key, ".", "/", -1)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 6405725ca2)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2025-04-24 02:35:52 +00:00
Aleksa Sarai 708fe7615f rootfs: improve error messages for bind-mount vfs flag setting
While debugging an issue involving failing mounts, I discovered that
just returning the plain mount error message when we are in the fallback
code for handling locked mounts leads to unnecessary confusion.

It also doesn't help that podman currently forcefully sets "rw" on
mounts, which means that rootless containers are likely to hit the
locked mounts issue fairly often.

So we should improve our error messages to explain why the mount is
failing in the locked flags case.

Fixes: 7c71a22705 ("rootfs: remove --no-mount-fallback and finally fix MS_REMOUNT")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 58c3ab77b0)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-23 12:40:35 +08:00
Aleksa Sarai 4f7de1e0d3 mount: add string representation of mount flags
When reading mount errors, it is quite hard to make sense of mount flags
in their hex form. As this is the error path, the minor performance
impact of constructing a string is probably not worth hyper-optimising.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 30302a2850)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-23 12:40:35 +08:00
Rodrigo Campos 8dd36d11ce libct: Override HOME if its set to the empty string
Before commit 06f1e0765 ("libct: speedup process.Env handling") we were
overriding HOME if it was set to "" too[1]. But now we only override it
if it wasn't set at all.

This patch restores the old behavior of overriding it if it was set to
an empty value.

Docker relies on this behaviour since ages[2].

[1]: https://github.com/opencontainers/runc/blob/1c508045727231e7342e258ab30add1478c1f981/libcontainer/init_linux.go#L544-L549
[2]: https://github.com/moby/moby/blob/843e51459f14ebc964d349eba1013dc8a3e9d52e/integration-cli/docker_cli_run_test.go#L822-L843

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
(cherry picked from commit 09501d96d2)
2025-04-07 14:17:11 +02:00
Rodrigo Campos fa44e9d503 Merge pull request #4705 from kolyshkin/1.3-4696
[1.3] criu: Add time namespace to container config after checkpoint/restore
2025-04-02 05:44:06 -03:00