This makes the state.json file 1303 bytes or almost 25% smaller (when
using the default spec, YMMV) by omitting default values.
Before: 5496 bytes
After: 4193 bytes
(With cgroups#9 applied, the new size is 3424, which is almost 40%
savings, compared to the original).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There is no behavior change, it is just more readable to use -1 to mean
don't touch this.
Please note that if the GID is not mapped in the userns, by using -1 for
that no error is returned. We just avoid dealing with it completely, as
we want here.
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
This addresses a TODO item added by commit 40f146841
("keyring: handle ENOSYS with keyctl(KEYCTL_JOIN_SESSION_KEYRING)"),
as we do have runc init logging working fine for quite some time.
While at it, fix a typo in a comment (standart -> standard).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Because we should switch to unix.PidFDSendSignal in new kernels, it has
been supported in go runtime. We don't need to add fall back to
unix.Kill code here.
Signed-off-by: lifubang <lifubang@acmcoder.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>