Commit Graph

3010 Commits

Author SHA1 Message Date
Kir Kolyshkin a75076b4a4 Switch to opencontainers/cgroups
This removes libcontainer/cgroups packages and starts
using those from github.com/opencontainers/cgroups repo.

Mostly generated by:

  git rm -f libcontainer/cgroups

  find . -type f -name "*.go" -exec sed -i \
    's|github.com/opencontainers/runc/libcontainer/cgroups|github.com/opencontainers/cgroups|g' \
    {} +

  go get github.com/opencontainers/cgroups@v0.0.1
  make vendor
  gofumpt -w .

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-28 15:20:33 -08:00
Rodrigo Campos 8c72dfae65 Merge pull request #4627 from beam-cloud/main
Add skip-in-flight and link-remap criu options for checkpoint and restore
2025-02-26 06:06:26 -03:00
Rodrigo Campos 352c8d40ac Merge pull request #4636 from lifubang/fix-exec-timens
libct: don't send config to nsexec when joining an existing timens
2025-02-26 05:53:29 -03:00
Tomasz Duda c43ea7d629 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>
2025-02-26 16:40:34 +11:00
Daniel Levi-Minzi 1d047e44ed expose criu options for link remap and skip in flight
Signed-off-by: Daniel Levi-Minzi <dleviminzi@gmail.com>
2025-02-25 10:35:31 -05:00
Aleksa Sarai 559bd4ebdf libcontainer: rename dmz -> exeseal
The "dmz" name was originally used because the libcontainer/dmz package
housed the runc-dmz binary, but since we removed it in commit
871057d863 ("drop runc-dmz solution according to overlay solution")
the name is an anachronism and we should just give it a more
self-explanatory name.

So, call it libcontainer/exeseal because the purpose of the package is
to provide tools to seal /proc/self/exe against attackers.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2025-02-25 13:46:05 +11:00
Aleksa Sarai ef9830a0bf merge #4513 into opencontainers/runc:main
Tomasz Duda (1):
  support cgroup v1 mounted with noprefix

LGTMs: kolyshkin cyphar
2025-02-25 13:21:49 +11:00
lfbzhm 5f8abe5754 Merge pull request #4637 from mirendev/evanphx/b-eintr
Retry direct unix package calls if observing EINTR
2025-02-25 08:24:20 +08:00
lifubang ad09197e41 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>
2025-02-22 16:42:33 +00:00
Evan Phoenix 28475f12e3 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>
2025-02-21 15:19:54 -08:00
Kir Kolyshkin 4e0f7a203d libct/cg/dev: remove specconv dependency
This was needed for a test case only, but we can easily copy the data
needed.

The alternatives are:
 - keep things as is (and have cgroups depend on
   runc/libcontainer/specconv);
 - remove this test case;
 - move AllowedDevices to cgroups/devices/config.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-21 14:23:58 -08:00
Kir Kolyshkin 69792827b4 libct/cg: don't use utils.CleanPath
Instead, we can just do filepath.Clean("/"+path) here.

While at it, add a comment telling why this is needed and important.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-21 14:23:58 -08:00
Kir Kolyshkin 5e1dcdf564 libct/cg: add internal/path.Inner
The code which determines inner cgroup path from cgroup config is
identical in fs and fs2 drivers, and it is using utils.CleanPath.

In preparation to move libcontainer/cgroups to a separate repo,
we have to get rid of libcontainer/utils dependency. So,
 - copy the utils.CleanPath implementation to internal/path;
 - consolidate the two innerPath implementations to internal/path.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-21 14:23:58 -08:00
Kir Kolyshkin 271aa88ed5 libct/cg/fs2: rm _defaultDirPath
The _defaultDirPath was only used for testing, and the test case
is quite easy to adopt to defaultDirPath.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-21 14:23:58 -08:00
Kir Kolyshkin 7bebe68c7a libct/cg: stop using utils.ProcThreadSelf
We were using utils.ProcThreadSelf since commit 8e8b136c,
which provides two things:
1. locking the OS tread;
2. fallback to /proc/self/task/$TID when /proc/thread-self
   is not available (kernel < 3.17).

Now, (1) is not needed since we only call readlink and not perform any
file data operation, and (2) is not needed here as this code is
only running when openat2 syscall is available, meaning kernel >= v5.6.

Also, check the error from readlink, so when it fails, we do not try to
enhance the error message.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-21 14:14:22 -08:00
Rodrigo Campos b0b186e64d Merge pull request #4630 from kolyshkin/clean-path
libc/utils: simplify CleanPath
2025-02-13 13:59:23 -03:00
lfbzhm c3c111d2a6 Merge pull request #4585 from kolyshkin/per-process-properties
Fix process/config properties merging
2025-02-13 18:47:32 +08:00
Rodrigo Campos 20727c62d5 Merge pull request #4598 from kolyshkin/go124
Add Go 1.24, drop Go 1.22
2025-02-13 07:46:47 -03:00
Kir Kolyshkin 0f88286077 Merge pull request #4470 from kolyshkin/strings-cut
Use strings.Cut and strings.CutPrefix where possible
2025-02-12 23:35:20 -08:00
Kir Kolyshkin 8db6ffbeef libc/utils: simplify CleanPath
This simplifies the code flow and basically removes the last
filepath.Clean, which is not necessary in either case:

 - for absolute path, single filepath.Clean is enough (as it is
   guaranteed to remove all dot and dot-dot elements);

 - for relative path, filepath.Rel calls Clean at the end
   (which is even documented).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-12 20:17:51 -08:00
ningmingxiao 6a3f8ea3b4 skip read /proc/filesystems if process_label is null
Signed-off-by: ningmingxiao <ning.mingxiao@zte.com.cn>
2025-02-12 12:44:39 +08:00
Kir Kolyshkin 35a28ad0a4 Merge pull request #4596 from evanphx/evanphx/b-close-range
utils: Handle close_range more gracefully
2025-02-11 18:04:07 -08:00
Kir Kolyshkin 16d7336791 Require Go 1.23.x, drop Go 1.22 support
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:03:06 -08:00
Kir Kolyshkin 99f9ed94dc runc exec: fix setting process.Scheduler
Commit 770728e1 added Scheduler field into both Config and Process,
but forgot to add a mechanism to actually use Process.Scheduler.
As a result, runc exec does not set Process.Scheduler ever.

Fix it, and a test case (which fails before the fix).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
Kir Kolyshkin b9114d91e2 runc exec: fix setting process.ioPriority
Commit bfbd0305b added IOPriority field into both Config and Process,
but forgot to add a mechanism to actually use Process.IOPriority.
As a result, runc exec does not set Process.IOPriority ever.

Fix it, and a test case (which fails before the fix).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
Kir Kolyshkin 73849e797f libct: simplify Caps inheritance
For all other properties that are available in both Config and Process,
the merging is performed by newInitConfig.

Let's do the same for Capabilities for the sake of code uniformity.

Also, thanks to the previous commit, we no longer have to make sure we
do not call capabilities.New(nil).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
Kir Kolyshkin 049a5f76cf libct/cap: allow New(nil)
In runtime-spec, capabilities property is optional, but
libcontainer/capabilities panics when New(nil) is called.

Because of this, there's a kludge in finalizeNamespace to ensure
capabilities.New is not called with nil argument, and there's a
TestProcessEmptyCaps to ensure runc won't panic.

Let's fix this at the source, allowing libct/cap to work with nil
capabilities.

(The caller is fixed by the next commit.)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
Kir Kolyshkin f26ec92221 libct: rm Rootless* properties from initConfig
They are passed in initConfig twice, so it does not make sense.

NB: the alternative to that would be to remove Config field from
initConfig, but it results in a much bigger patch and more maintenance
down the road.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
Kir Kolyshkin 2a86c35768 libct: document initConfig and friends
This is one of the dark corners of runc / libcontainer, so let's shed
some light on it.

initConfig is a structure which is filled in [mostly] by newInitConfig,
and one of its hidden aspects is it contains a process config which is
the result of merge between the container and the process configs.

Let's document how all this happens, where the fields are coming from,
which one has a preference, and how it all works.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-11 18:01:30 -08:00
lfbzhm 74b35d8927 Merge pull request #4592 from kolyshkin/exec-nits
Improvements to how `runc exec` is handled
2025-02-10 18:32:33 +08:00
lfbzhm bf0f67f7f2 Merge pull request #4597 from evanphx/evanphx/b-graceful-ambient
capabilities: be more graceful in resetting ambient
2025-02-10 18:28:52 +08:00
Kir Kolyshkin c4eb0c61e1 libct: createExecFifo: optimize
Every time we call container.Config(), a new copy of
struct Config is created and returned, and we do it twice here.

Accessing container.config directly fixes this.

Fixes: 805b8c73d ("Do not create exec fifo in factory.Create")
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 22:56:11 -08:00
Kir Kolyshkin 746a5c23c9 libcontainer/configs/validate: improve rootlessEUIDMount
1. Avoid splitting mount data into []string if it does not contain
   options we're interested in. This should result in slightly less
   garbage to collect.

2. Use if / else if instead of continue, to make it clearer that
   we're processing one option at a time.

3. Print the whole option as a sting in an error message; practically
   this should not have any effect, it's just simpler.

4. Improve some comments.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:47:23 -08:00
Kir Kolyshkin 055041e874 libct: use strings.CutPrefix where possible
Using strings.CutPrefix (available since Go 1.20) instead of
strings.HasPrefix and/or strings.TrimPrefix makes the code
a tad more straightforward.

No functional change.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:35 -08:00
Kir Kolyshkin 259b71c042 libct/utils: stripRoot: rm useless HasPrefix
Using strings.HasPrefix with strings.TrimPrefix results in doing the
same thing (checking if prefix exists) twice. In this case, using
strings.TrimPrefix right away is sufficient.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:35 -08:00
Kir Kolyshkin ecf74300c0 libct/cg/fscommon: GetCgroupParam*: unify
1. GetCgroupParamUint: drop strings.TrimSpace since it was already
   done by GetCgroupParamString.

2. GetCgroupParamInt: use GetCgroupParamString, drop strings.TrimSpace.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:35 -08:00
Kir Kolyshkin ef983f5180 libct/cg/fscommon: ParseKeyValue: stricter check
It makes sense to report an error if a key or a value is empty,
as we don't expect anything like this.

Reported-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:34 -08:00
Kir Kolyshkin d83d533bba libct/cg/fscommon: GetValueByKey: use strings.CutPrefix
Using strings.CutPrefix (added in Go 1.20, see [1]) results in faster and
cleaner code with less allocations (as the code only allocates memory
for the value, and does it once).

While at it, improve the function documentation.

[1]: https://github.com/golang/go/issues/42537

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:34 -08:00
Kir Kolyshkin f134871206 libct/cg/fscommon: ParseKeyValue: use strings.Cut
Using strings.Cut (added in Go 1.18, see [1]) results in faster and
cleaner code with less allocations (as we're not using a slice).

[1]: https://github.com/golang/go/issues/46336

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin e9855bdae9 libct/cg/fscommon: use strings.Cut in RDMA parser
Using strings.Cut (added in Go 1.18, see [1]) results in faster and
cleaner code with less allocations (as we're not using a slice).

Also, use switch in parseRdmaKV.

[1]: https://github.com/golang/go/issues/46336

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin 930cd4944a libct/cg/fs2: use strings.Cut in parsePSIData
Using strings.Cut (added in Go 1.18, see [1]) results in faster and
cleaner code with less allocations (as we're not using a slice).

This code is tested by TestStatCPUPSI.

[1]: https://github.com/golang/go/issues/46336

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin 40ce69cc9e libct/cg/fs2: use strings.Cut in setUnified
Using strings.Cut (added in Go 1.18, see [1]) results in faster and
cleaner code with less allocations (as we're not using a slice).

The code is tested by testCgroupResourcesUnified.

[1]: https://github.com/golang/go/issues/46336

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin 037668e501 libct/cg/fs2: simplify parseCgroupFromReader
For cgroup v2, we always expect /proc/$PID/cgroup contents like this:

> 0::/user.slice/user-1000.slice/user@1000.service/app.slice/vte-spawn-f71c3fb8-519d-4e2d-b13e-9252594b1e05.scope

So, it does not make sense to parse it using strings.Split, we can just
cut the prefix and return the rest.

Code tested by TestParseCgroupFromReader.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin 075cea3a45 libcontainer/cgroups/fs: some refactoring
Remove extra global constants that are only used in a single place and
make it harder to read the code.

Rename nanosecondsInSecond -> nsInSec.

This code is tested by unit tests.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin 4271ecf73f libct/cg/fs: refactor getCpusetStat
Using strings.Cut (added in Go 1.18, see [1]) results in faster and
cleaner code with less allocations (as we're not using a slice). This
also drops the check for extra dash (we're unlikely to get it from the
kernel anyway).

While at it, rename min/max -> from/to to avoid collision with Go
min/max builtins.

This code is tested by TestCPUSetStats* tests.

[1]: https://github.com/golang/go/issues/46336

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Kir Kolyshkin bfcd479c5d libct/cg/fs: getPercpuUsage: rm TODO
Nowadays strings.Fields are as fast as strings.SplitN so remove TODO.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 19:42:02 -08:00
Akihiro Suda e6c4c9c680 Merge pull request #4616 from kolyshkin/fix-cross-build
libc/int/userns: add build tag to C file
2025-02-07 11:37:34 +09:00
Akihiro Suda dadea505df Merge pull request #4612 from kolyshkin/fix-systemd-reload
libct/cg/sd: set the DeviceAllow property before DevicePolicy
2025-02-07 11:37:10 +09:00
Kir Kolyshkin 52f702af56 libct: earlier Rootless vs AdditionalGroups check
Since the UID/GID/AdditonalGroups fields are now numeric,
we can address the following TODO item in the code (added
by commit d2f49696 back in 2016):

> TODO: We currently can't do
> this check earlier, but if libcontainer.Process.User was typesafe
> this might work.

Move the check to much earlier phase, when we're preparing
to start a process in a container.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 17:49:17 -08:00
Kir Kolyshkin 7dc2486889 libct: switch to numeric UID/GID/groups
This addresses the following TODO in the code (added back in 2015
by commit 845fc65e5):

> // TODO: fix libcontainer's API to better support uid/gid in a typesafe way.

Historically, libcontainer internally uses strings for user, group, and
additional (aka supplementary) groups.

Yet, runc receives those credentials as part of runtime-spec's process,
which uses integers for all of them (see [1], [2]).

What happens next is:

1. runc start/run/exec converts those credentials to strings (a User
   string containing "UID:GID", and a []string for additional GIDs) and
   passes those onto runc init.
2. runc init converts them back to int, in the most complicated way
   possible (parsing container's /etc/passwd and /etc/group).

All this conversion and, especially, parsing is totally unnecessary,
but is performed on every container exec (and start).

The only benefit of all this is, a libcontainer user could use user and
group names instead of numeric IDs (but runc itself is not using this
feature, and we don't know if there are any other users of this).

Let's remove this back and forth translation, hopefully increasing
runc exec performance.

The only remaining need to parse /etc/passwd is to set HOME environment
variable for a specified UID, in case $HOME is not explicitly set in
process.Env. This can now be done right in prepareEnv, which simplifies
the code flow a lot. Alas, we can not use standard os/user.LookupId, as
it could cache host's /etc/passwd or the current user (even with the
osusergo tag).

PS Note that the structures being changed (initConfig and Process) are
never saved to disk as JSON by runc, so there is no compatibility issue
for runc users.

Still, this is a breaking change in libcontainer, but we never promised
that libcontainer API will be stable (and there's a special package
that can handle it -- github.com/moby/sys/user). Reflect this in
CHANGELOG.

For 3998.

[1]: https://github.com/opencontainers/runtime-spec/blob/v1.0.2/config.md#posix-platform-user
[2]: https://github.com/opencontainers/runtime-spec/blob/v1.0.2/specs-go/config.go#L86

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2025-02-06 17:49:17 -08:00