As per
- https://github.com/opencontainers/runtime-spec/pull/1253
- https://github.com/opencontainers/runtime-spec/pull/1261
CPU affinity can be set in two ways:
1. When creating/starting a container, in config.json's
Process.ExecCPUAffinity, which is when applied to all execs.
2. When running an exec, in process.json's CPUAffinity, which
applied to a given exec and overrides the value from (1).
Add some basic tests.
Note that older kernels (RHEL8, Ubuntu 20.04) change CPU affinity of a
process to that of a container's cgroup, as soon as it is moved to that
cgroup, while newer kernels (Ubuntu 24.04, Fedora 41) don't do that.
Because of the above,
- it's impossible to really test initial CPU affinity without adding
debug logging to libcontainer/nsenter;
- for older kernels, there can be a brief moment when exec's affinity
is different than either initial or final affinity being set;
- exec's final CPU affinity, if not specified, can be different
depending on the kernel, therefore we don't test it.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There is a big loop(at least 65 times) in `signal.Notify`, it costs as much
time as `runc init`, so we can call it in parallel ro reduce the container
start time. In a general test, it can be reduced about 38.70%.
Signed-off-by: lifubang <lifubang@acmcoder.com>
(cyphar: move signal channel definition inside goroutine)
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
There is an announce that Ubuntu 20.04 will be removed in April,
and in March there will be a few "brown-out" dates/times when
it won't work.
This leaves us with no other options than to remove ubuntu-20.04
from the testing matrix.
As a result, cgroup v1 testing will only be done on AlmaLinux 8
running on CirrusCI. It is probably going to be sufficient for
the time being (until we deprecate cgroup v1).
If not, our options are
- run Ubuntu 20.04 (or other cgroup v1 distro) in a VM on GHA;
- switch to cirrus-ci.
[1]: https://github.com/actions/runner-images/issues/11101
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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>
On my machine, the --recv-keys steps to get upstream keys started
producing errors recently, and even setting a default keyserver in the
global gpg configuration doesn't seem to help:
+ gpg --homedir=/tmp/runc-sign-tmpkeyring.qm0IP6
--no-default-keyring --keyring=seccomp.keyring
--recv-keys 0x47A68FCE37C7D7024FD65E11356CE62C2B524099
gpg: keybox '/tmp/runc-sign-tmpkeyring.qm0IP6/seccomp.keyring' created
gpg: keyserver receive failed: No keyserver available
So just explicitly specify a reputable keyserver. Ideally we would use
an .onion-address keyserver to avoid potential targeted attacks but not
everybody runs a Tor proxy on their machine.
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
A new libseccomp releases (v2.5.6 and v2.6.0) were cut last month.
Theoretically, we could use v2.6.0 but let's stay conservative for now.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>