Commit Graph

2792 Commits

Author SHA1 Message Date
Kir Kolyshkin 66888fb75c 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:29:05 +08:00
Kir Kolyshkin 8559d3e527 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:29:05 +08:00
Kir Kolyshkin 83a3755693 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:29:05 +08:00
Kir Kolyshkin 881a781eed 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:29:05 +08:00
Aleksa Sarai 6983cc7ac1 [1.2] 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 11:02:54 +10:00
Aleksa Sarai ae93828c27 [1.2] 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:19:15 +10:00
Yusuke Sakurai 2667d7365b fix rootfs propagation mode
Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com>
(cherry picked from commit 04be81b6a3)
2025-07-16 12:03:47 +02:00
Pavel Liubimov 3e32756ef7 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:11:13 +03:00
Aleksa Sarai 3954766557 [1.2] 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")
(cherry picked from commit 58c3ab77b0)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-04-23 14:35:34 +10:00
Aleksa Sarai dc0c6d0163 [1.2] 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.

(cherry pick from commit 30302a2850)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-04-23 14:35:34 +10:00
Andrei Vagin c248c8ecdf criu: Add time namespace to container config after checkpoint/restore
Since v3.14, CRIU always restores processes into a time namespace to
prevent backward jumps of monotonic and boottime clocks. This change
updates the container configuration to ensure that `runc exec` launches
new processes within the container's time namespace.

Fixes #2610

Signed-off-by: Andrei Vagin <avagin@gmail.com>
(cherry picked from commit b68cbdff34)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-04-07 17:09:08 -07:00
Aleksa Sarai 4dbf9ac5ae merge #4647 into opencontainers/runc:release-1.2
Evan Phoenix (1):
  libcontainer: Prevent startup hang when CloseExecFrom errors

LGTMs: lifubang cyphar
2025-02-27 16:06:02 +11:00
Aleksa Sarai 35d1d6e7a0 merge #4649 into opencontainers/runc:release-1.2
lifubang (2):
  libct: don't send config to nsexec when joining an existing timens
  test: exec into a container with private time ns

LGTMs: cyphar lifubang
2025-02-27 16:05:17 +11:00
Aleksa Sarai 58c8c815b0 merge #4650 into opencontainers/runc:release-1.2
Evan Phoenix (1):
  Retry direct unix package calls if observing EINTR

LGTMs: cyphar lifubang
2025-02-27 16:04:42 +11:00
lfbzhm 13d44fb2aa Merge pull request #4651 from kolyshkin/1.2-4641
[1.2] exeseal: do not use F_SEAL_FUTURE_WRITE
2025-02-27 12:45:13 +08:00
Evan Phoenix e64390545e libcontainer: Prevent startup hang when CloseExecFrom errors
The previous logic caused runc to hang if CloseExecFrom returned an
error, as the defer waiting on logsDone never finished as the parent
process was never started (and it controls the closing of logsDone via
it's logsPipe).

This moves the defer to after we have started the parent, with means all
the logic related to managing the logsPipe should also be running.

Signed-off-by: Evan Phoenix <evan@phx.io>
(cherry picked from commit 7b26da9ee3)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-27 11:25:10 +08:00
Tomasz Duda e11430aa50 exeseal: do not use F_SEAL_FUTURE_WRITE
Prior to kernel Linux 5.5, F_SEAL_FUTURE_WRITE has a bug which maps
memory as shared between processes even if it is set as private. See
kernel commit 05d351102dbe ("mm, memfd: fix COW issue on MAP_PRIVATE and
F_SEAL_FUTURE_WRITE mappings") for more details.

According to the fcntl(2) man pages, F_SEAL_WRITE is enough:

> Furthermore, trying to create new shared, writable memory-mappings via
> mmap(2) will also fail with EPERM.
>
> Using the F_ADD_SEALS operation to set the F_SEAL_WRITE seal fails
> with EBUSY if any writable, shared mapping exists. Such mappings must
> be unmapped before you can add this seal.

F_SEAL_FUTURE_WRITE only makes sense if a read-write shared mapping in
one process should be read-only in another process. This is not case for
runc, especially not for the /proc/self/exe we are protecting.

Signed-off-by: Tomasz Duda <tomaszduda23@gmail.com>
(cyphar: improve the comment regarding F_SEAL_FUTURE_WRITE)
(cyphar: improve commit message)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit c43ea7d629)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-26 13:29:36 -08:00
Evan Phoenix 68a76952a0 Retry direct unix package calls if observing EINTR
Retry Recvfrom, Sendmsg, Readmsg, and Read as they can return EINTR.

Signed-off-by: Evan Phoenix <evan@phx.io>
(cherry picked from commit 28475f12e3)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-26 13:26:52 -08:00
lifubang c5312bc308 libct: don't send config to nsexec when joining an existing timens
We should configure the process's timens offset only when we need to
create new time namespace, we shouldn't do it if we are joining an
existing time namespace. (#4635)

Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit ad09197e41)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-26 13:23:36 -08:00
Kir Kolyshkin f5f6e758f8 libct/system: rm Fexecve
This helper was added for runc-dmz in commit dac417174, but runc-dmz was
later removed in commit 871057d, which forgot to remove the helper.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 83350c24a9)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-26 11:46:10 -08:00
Akihiro Suda d0ed7f7ae6 Merge pull request #4619 from kolyshkin/1.2-4616
[1.2] libc/int/userns: add build tag to C file
2025-02-07 13:34:05 +09:00
Brad Davidson 04468c038d libc/int/userns: add build tag to C file
This fixes k3s cross-compilation on Windows, broken by commit
1912d5988b ("*: actually support joining a userns with a new
container").

[@kolyshkin: commit message]

Fixes: 1912d5988b
Signed-off-by: Brad Davidson <brad.davidson@rancher.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit ccb589bd7d)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:10:39 -08:00
Kir Kolyshkin 9742b6cf10 libct/cg/sd: set the DeviceAllow property before DevicePolicy
Every unit created by runc need daemon reload since systemd v230.
This breaks support for NVIDIA GPUs, see
https://github.com/opencontainers/runc/issues/3708#issuecomment-2216967210

A workaround is to set DeviceAllow before DevicePolicy.

Also:
 - add a test case (which fails before the fix) by @kolyshkin
 - better explain why we need empty DeviceAllow (by @cyphar)

Fixes 4568.

Reported-by: Jian Wen <wenjianhn@gmail.com>
Co-authored-by: Jian Wen <wenjianhn@gmail.com>
Co-authored-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit d84388ae10)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-05 12:18:12 -08:00
Aleksa Sarai 00f4a5cc4f deps: update to github.com/cyphar/filepath-securejoin@v0.4.1
This release includes a minor breaking API change that requires us to
rework the types of our wrappers, but there is no practical behaviour
change.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 70e500e7d1)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-05 22:05:15 +11:00
Kir Kolyshkin 33ed43bdfa [1.2] Re-add tun/tap to default device rules
Since v1.2.0 was released, a number of users complained that the removal
of tun/tap device access from the default device ruleset is causing a
regression in their workloads.

Additionally, it seems that some upper-level orchestration tools
(Docker Swarm, Kubernetes) makes it either impossible or cumbersome
to supply additional device rules.

While it's probably not quite right to have /dev/net/tun in a default
device list, it was there from the very beginning, and users rely on it.
Let's keep it there for the sake of backward compatibility.

This reverts commit 2ce40b6ad7.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(Cherry-pick of commit 394f4c3b7012674ebe0232c560713e57cbd653e6.)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2024-12-17 14:14:11 +11:00
Aleksa Sarai 7242ffa4bf [1.2] cgroup: ebpf: make unexpected errors in haveBpfProgReplace louder
(This is a cherry-pick of c0044c7aa403ecf2d9172bd9386d05433b011076.)

If we get an unexpected error here, it is probably because of a library
or kernel change that could cause our detection logic to be invalid. As
a result, these warnings should be louder so users have a chance to tell
us about them sooner (or so we might notice them before doing a release,
as happened with the 1.2.0 regression).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2024-12-08 00:21:59 +11:00
Aleksa Sarai e26e0fde01 [1.2] cgroups: ebpf: also check for ebpf.ErrNotSupported
(This is a cherry-pick of dea0e04dd93d3922083e68667d20aac532d31129.)

It is possible for LinkAttachProgram to return ErrNotSupported if
program attachment is not supported at all (which doesn't matter in this
case), but it seems possible that upstream will start returning
ErrNotSupported for BPF_F_REPLACE at some point so it's best to make
sure we don't cause additional regressions here.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2024-12-08 00:21:49 +11:00
Aleksa Sarai e623414959 [1.2] cgroups: ebpf: use link.Anchor to check for BPF_F_REPLACE support
(This is a cherry-pick of dea0e04dd93d3922083e68667d20aac532d31129.)

In v0.13.0, cilium/ebpf stopped supporting setting BPF_F_REPLACE as an
explicit flag and instead requires us to use link.Anchor to specify
where the program should be attached.

Commit 216175a9ca ("Upgrade Cilium's eBPF library version to 0.16")
did update this correctly for the actual attaching logic, but when
checking for kernel support we still passed BPF_F_REPLACE. This would
result in a generic error being returned, which our feature-support
checking logic would treat as being an error the indicates that
BPF_F_REPLACE *is* supported, resulting in a regression on pre-5.6
kernels.

It turns out that our debug logging saying that this unexpected error
was happening was being output as a result of this change, but nobody
noticed...

Fixes: 216175a9ca ("Upgrade Cilium's eBPF library version to 0.16")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2024-12-08 00:21:22 +11:00
Aleksa Sarai b1f733b8ed dmz: overlay: set xino=off to disable dmesg spam
If /run/runc and /usr/bin are on different filesystems, overlayfs may
enable the xino feature which results in the following log message:

  kernel: overlayfs: "xino" feature enabled using 3 upper inode bits.

Each time we have to protect /proc/self/exe. So disable xino to remove
the log message (we don't care about the inode numbers of the files
anyway).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
(cherry picked from commit 9bc42d61bb)
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-11-15 10:28:39 -08:00
lfbzhm 832faf08fa libct/cg: add test for remove a non-existent dir in a ro mount point
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
(cherry picked from commit 119111a0df)
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-11-15 00:00:15 +00:00
Kir Kolyshkin e41cc272b6 libct/cg: RemovePath: improve comments
Let's explain in greater details what's happening here and why.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit ba3d026e52)
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-11-13 13:51:20 +00:00
Kir Kolyshkin 79cdf119b6 libct/cg: RemovePath: simplify logic
If the sub-cgroup RemovePath has failed for any reason, return the
error right away. This way, we don't have to check for err != nil
before retrying rmdir.

This is a cosmetic change and should not change any functionality.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 12e06a7c4f)
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-11-13 13:51:20 +00:00
Kir Kolyshkin e01db0028d runc delete: fix for rootless cgroup + ro cgroupfs
An issue with runc 1.2.0 was reported to buildkit, in which
runc delete returns with an error, with the log saying:

> unable to destroy container: unable to remove container's cgroup: open /sys/fs/cgroup/snschvixiy3s74w74fjantrdg: no such file or directory

Apparently, what happens is runc is running with no cgroup access
(because /sys/fs/cgroup is mounted read-only). In this case error to
create a cgroup path (in runc create/run) is ignored, but cgroup removal
(in runc delete) is not.

This is caused by commit d3d7f7d, which changes the cgroup removal
logic in RemovePath. In the current code, if the initial rmdir has
failed (in this case with EROFS), but the subsequent os.ReadDir returns
ENOENT, it is returned (instead of being ignored -- as the path does not
exist and so there is nothing to remove).

Here is the minimal fix for the issue.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit db59489b68)
Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-11-13 13:51:20 +00:00
Rodrigo Campos 360f8f9dbd Merge pull request #4494 from kolyshkin/12-4490
[1.2] Post overlay addition and dmz removal nits
2024-11-01 19:04:16 +01:00
Kir Kolyshkin 258cd8b64b libct: rm obsoleted comment
This was added by commit f2f16213e when runc-dmz was still a thing.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 5586d7caa1)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2024-11-01 10:19:12 -07:00
Kir Kolyshkin b798594cf9 libct: fix a comment
There is a typo in the comment (ClonedBinary should be CloneBinary), and
the code has changed a bit since then, and it makes more sense to refer
to CloneSelfExe now.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 8cc7375447)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2024-11-01 10:19:12 -07:00
Kir Kolyshkin e0d39536c4 runc update: fix updating swap for cgroup v2
This allows to do

	runc update $ID --memory=-1 --memory-swap=$VAL

for cgroup v2, i.e. set memory to unlimited and swap to a specific
value.

This was not possible because ConvertMemorySwapToCgroupV2Value rejected
memory=-1 ("unlimited"). In a hindsight, it was a mistake, because if
memory limit is unlimited, we should treat memory+swap limit as just swap
limit.

Revise the unit test; add description to each case.

Fixes: c86be8a2 ("cgroupv2: fix setting MemorySwap")
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit 732806e24c)
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2024-11-02 01:58:28 +09:00
Kir Kolyshkin 914a8f35ad libct/cg: improve ConvertMemorySwapToCgroupV2Value
Improve readability of ConvertMemorySwapToCgroupV2Value by switching
from a bunch of if statements to a switch, and adding a comment
describing each case.

No functional change.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit cb9f3d6d14)
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2024-11-02 01:58:20 +09:00
lifubang f07d92dbcd drop runc-dmz solution according to overlay solution
Because we have the overlay solution, we can drop runc-dmz binary
solution since it has too many limitations.

Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit 871057d863)
Signed-off-by: lifubang <lifubang@acmcoder.com>
2024-10-29 17:52:12 +08:00
Kir Kolyshkin f479676cce libct: rm x/sys/execabs usage
Since Go 1.19, the same functionality is there in os/exec package.
As we require go 1.22 now, there's no need to have this.

This basically reverts commit 9258eac0 ("libct/start: use execabs for
newuidmap lookup").

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
(cherry picked from commit eb2ff52ace)
Signed-off-by: Austin Vazquez <macedonv@amazon.com>
2024-10-26 18:27:18 +00:00
lifubang 1eb9ad3edf libct/nsenter: become root after joining userns
Containerd pre-creates userns and netns before calling runc, which
results in the current code not working when SELinux is enabled,
resulting in the following error:

> runc create failed: unable to start container process: error during
container init: error mounting "mqueue" to rootfs at "/dev/mqueue":
setxattr /path/to/rootfs/dev/mqueue: operation not permitted

The solution is to become root in the user namespace right after
we join it.

Fixes #4466.

Co-authored-by: Wei Fu <fuweid89@gmail.com>
Co-authored-by: Kir Kolyshkin <kolyshkin@gmail.com>
Co-authored-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cherry picked from commit c78f3f2ea0)
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2024-10-25 18:13:58 -07:00
lfbzhm e669926691 fix an error caused by fd reuse race when starting runc init
There is a race situation when we are opening a file, if there is a
small fd was closed at that time, maybe it will be reused by safeExe.
Because of Go stdlib fds shuffling bug, if the fd of safeExe is too
small, go stdlib will dup3 it to another fd, or dup3 a other fd to this
fd, then it will cause the fd type cmd.Path refers to a random path,
and it can lead to an error "permission denied" when starting the process.
Please see #4294 and <https://github.com/golang/go/issues/61751>.
So we should not use the original fd of safeExe, but use the fd after
shuffled by Go stdlib. Because Go stdlib will guarantee this fd refers to
the correct file.

Signed-off-by: lfbzhm <lifubang@acmcoder.com>
2024-10-21 06:53:44 +00:00
Akihiro Suda ca8ca3ce07 Merge pull request #4448 from cyphar/cloned-binary-overlayfs
dmz: use overlayfs to write-protect /proc/self/exe if possible
2024-10-21 04:11:33 +09:00
Akihiro Suda 08faf15106 Merge pull request #4429 from kolyshkin/cap-load
libct/cap: no need to load capabilities
2024-10-21 04:09:07 +09:00
Aleksa Sarai 515f09f7b1 dmz: use overlayfs to write-protect /proc/self/exe if possible
Commit b999376fb2 ("nsenter: cloned_binary: remove bindfd logic
entirely") removed the read-only bind-mount logic from our cloned binary
code because it wasn't really safe because a container with
CAP_SYS_ADMIN could remove the MS_RDONLY bit and get write access to
/proc/self/exe (even with user namespaces this could've been an issue
because it's not clear if the flags are locked).

However, copying a binary does seem to have a minor performance impact.
The only way to have no performance impact would be for the kernel to
block these write attempts, but barring that we could try to reduce the
overhead by coming up with a mount that cannot have it's read-only bits
cleared.

The "simplest" solution is to create a temporary overlayfs using
fsopen(2) which uses the directory where runc exists as a lowerdir,
ensuring that the container cannot access the underlying file -- and we
don't have to do any copies.

While fsopen(2) is not free because mount namespace cloning is usually
expensive (and so it seems like the difference would be marginal), some
basic performance testing seems to indicate there is a ~60% improvement
doing it this way and that it has effectively no overhead even when
compared to just using /proc/self/exe directly:

  % hyperfine --warmup 50 \
  >           "./runc-noclone run -b bundle ctr" \
  >           "./runc-overlayfs run -b bundle ctr" \
  >           "./runc-memfd run -b bundle ctr"

  Benchmark 1: ./runc-noclone run -b bundle ctr
    Time (mean ± σ):      13.7 ms ±   0.9 ms    [User: 6.0 ms, System: 10.9 ms]
    Range (min … max):    11.3 ms …  16.1 ms    184 runs

  Benchmark 2: ./runc-overlayfs run -b bundle ctr
    Time (mean ± σ):      13.9 ms ±   0.9 ms    [User: 6.2 ms, System: 10.8 ms]
    Range (min … max):    11.8 ms …  16.0 ms    180 runs

  Benchmark 3: ./runc-memfd run -b bundle ctr
    Time (mean ± σ):      22.6 ms ±   1.3 ms    [User: 5.7 ms, System: 20.7 ms]
    Range (min … max):    19.9 ms …  26.5 ms    114 runs

  Summary
    ./runc-noclone run -b bundle ctr ran
      1.01 ± 0.09 times faster than ./runc-overlayfs run -b bundle ctr
      1.65 ± 0.15 times faster than ./runc-memfd run -b bundle ctr

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2024-10-20 21:35:09 +11:00
Kir Kolyshkin b5bdf592f2 libct: rm initWaiter
This initWaiter logic was introduced by commit 4ecff8d9, but since the logic of
/proc/self/exe was moved out of runc init in commit 0e9a335, this
seems unnecessary to have initWaiter.

Remove it.

This essentially reverts commit 4ecff8d9.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2024-10-17 08:05:42 -07:00
lifubang 9fa324c479 dmz: cloned binary: set +x permissions when creating regular tmpfile
While we did set +x when "sealing" regular temporary files, the "is
executable" checks were done before then and would thus fail, causing
the fallback to not work properly.

So just set +x after we create the file. We already have a O_RDWR handle
open when we do the chmod so we won't get permission issues when writing
to the file.

Fixes: e089db3b4a ("dmz: add fallbacks to handle noexec for O_TMPFILE and mktemp()")

Signed-off-by: lifubang <lifubang@acmcoder.com>
2024-10-14 17:48:18 +08:00
Kir Kolyshkin eff6f049bc libct/cap: no need to load capabilities
We are not really interested in the capabilities of the current process,
so there is no need to load those.

This results in some performance improvement since now the capability
package don't have to parse /proc/self/status.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2024-10-09 12:08:44 -07:00
Sebastiaan van Stijn 9b60a93cf3 libcontainer/userns: migrate to github.com/moby/sys/userns
The userns package was moved to the moby/sys/userns module
at commit 3778ae603c.

This patch deprecates the old location, and adds it as an alias
for the moby/sys/userns package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-10-09 22:20:25 +08:00
Kir Kolyshkin f2d56241d8 Merge pull request #4405 from amghazanfari/main
replace strings.SplitN with strings.Cut
2024-10-04 14:01:23 -07:00