Commit d08bc0c1b3 ("runc run: warn on non-empty cgroup") introduced
a warning when a container is started in a non-empty cgroup. Such
configuration has lots of issues.
In addition to that, such configuration is not possible at all when
using the systemd cgroup driver.
As planned, let's promote this warning to an error, and fix the test
case accordingly.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
In case a systemd unit fails (for example, timed out or OOM-killed),
systemd keeps the unit. This prevents starting a new container with
the same systemd unit name.
The fix is to call reset-failed in case UnitExists error is returned,
and retry once.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Commit d223e2adae ("Ignore error when starting transient unit
that already exists" modified the code handling errors from startUnit
to ignore UnitExists error.
Apparently it was done so that kubelet can create the same pod slice
over and over without hitting an error (see [1]).
While it works for a pod slice to ensure it exists, it is a gross bug
to ignore UnitExists when creating a container. In this case, the
container init PID won't be added to the systemd unit (and to the
required cgroup), and as a result the container will successfully
run in a current user cgroup, without any cgroup limits applied.
So, fix the code to only ignore UnitExists if we're not adding a process
to the systemd unit. This way, kubelet will keep working as is, but
runc will refuse to create containers which are not placed into a
requested cgroup.
[1] https://github.com/opencontainers/runc/pull/1124
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This fixes a bogus failure in "ro cgroup" test cases when running as
rootless.
The test finds the following mount that is not read-only:
> cgroup2 /sys/fs/cgroup/unified cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0
This happens because:
1. runc spec --rootless adds an rbind /sys mounts, so we have all the
/sys/fs/cgroup/XXX mounts inside the container;
2. Those /sys/fs/cgroup/XXX mounts are shadowed by the /sys/fs/cgroup
tmpfs mount created by mountCgroupV1().
This means that this mount is shadowed, inaccessible, and it can not be
unshadowed, thus it should not be checked.
The fix is to check whether the directory exists, to exclude such
shadowed mounts.
NOTE that item 2 comes from commit ff692f289b60e19b3079cb; before it, we
had the whole hierarchy of host /sys/fs/cgroup visible (though not
writable -- because rootless) from inside of any rootless container.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Fix the following issues with the "ro /sys/fs/cgroup" test:
1. Disable bogus SC2016 warning from shellcheck.
2. Split the test into two -- with and without cgroupns. This is done
because not all systems have cgroupns available (so the "+cgroupns"
test will be skipped).
3. This splitting resulted in a few more bogus shellcheck warnings that
we have to suppress -- due to a known bug in shellcheck (see [1]).
4. s/mount/mounts/ in the test name, because in case of cgroup v1 there
are multiple mounts.
[1] https://github.com/koalaman/shellcheck/issues/2431
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This is a test case for issue reported as #3715. In short, even if a
(non-root) user that the container is run as does not have execute
permission bit set for the executable, it should still work in case runc
has the CAP_DAC_OVERRIDE capability set.
Note that since the upstream golang is also broken (see [1]), this test
will fail for Go 1.20 and 1.20.1 (fix is in Go 1.20.2 as per [2]).
[1] https://go.dev/issue/58552
[2] https://go-review.googlesource.com/c/go/+/469956
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Go 1.20.2 has an important fix to an issue described in [1].
Switch from using Go 1.19 from Dockerfile, which is used for release
binaries and some CI.
[1] https://github.com/golang/go/issues/58624
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The setRecAttr is only called for "bind" case, as cases end with a
return statement. Indeed, recursive mount attributes only make sense for
bind mounts.
Move the code to under case "bind" to improve readability. No change in
logic.
Fixes: 382eba4354
Reported-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There is some kind of a race in CentOS 7 which sometimes result in one
of these tests failing like this:
systemd_test.go:136: mkdir /sys/fs/cgroup/hugetlb/system.slice/system-runc_test_pods.slice: no such file or directory
or
systemd_test.go:187: open /sys/fs/cgroup/cpuset/system.slice/system-runc_test_pods.slice/cpuset.mems: no such file or directory
As this is only happening on CentOS 7, let's skip this test on this
platform.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Commit 3291d66b98 introduced a check for /proc and /sys, making sure
the destination (dest) is a directory (and not e.g. a symlink).
Later, a hunk from commit 0ca91f44f switched from using filepath.Join
to SecureJoin for dest. As SecureJoin follows and resolves symlinks,
the check whether dest is a symlink no longer works.
To fix, do the check without/before using SecureJoin.
Add integration tests to make sure we won't regress.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Older kernels may return EINVAL on unshare when a process is reading
runc's /proc/$PID/status or /proc/$PID/maps. This was fixed by kernel
commit 12c641ab8270f ("unshare: Unsharing a thread does not require
unsharing a vm") in Linuxt v4.3.
For CentOS 7, the fix was backported to CentOS 7.7 (kernel 3.10.0-1062).
To work around this kernel bug, let's retry on EINVAL a few times.
Reported-by: zzyyzte <zhang.yu58@zte.com.cn>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
It was found that rootless runc makes `/sys/fs/cgroup` writable in following conditons:
1. when runc is executed inside the user namespace, and the config.json does not specify the cgroup namespace to be unshared
(e.g.., `(docker|podman|nerdctl) run --cgroupns=host`, with Rootless Docker/Podman/nerdctl)
2. or, when runc is executed outside the user namespace, and `/sys` is mounted with `rbind, ro`
(e.g., `runc spec --rootless`; this condition is very rare)
A container may gain the write access to user-owned cgroup hierarchy `/sys/fs/cgroup/user.slice/...` on the host.
Other users's cgroup hierarchies are not affected.
To fix the issue, this commit does:
1. Remount `/sys/fs/cgroup` to apply `MS_RDONLY` when it is being bind-mounted
2. Mask `/sys/fs/cgroup` when the bind source is unavailable
Fix CVE-2023-25809 (GHSA-m8cg-xc2p-r3fc)
Co-authored-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
The purpose of this test is to check that there are no extra file
descriptors left open after repeated calls to runContainer. In fact,
the first call to runContainer leaves a few file descriptors opened,
and this is by design.
Previously, this test relied on two things:
1. some other tests were run before it (and thus all such opened-once
file descriptors are already opened);
2. explicitly excluding fd opened to /sys/fs/cgroup.
Now, if we run this test separately, it will fail (because of 1 above).
The same may happen if the tests are run in a random order.
To fix this, add a container run before collection the initial fd list,
so those fds that are opened once are included and won't be reported.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>