Apparently, sometimes a short-lived "runc run" produces result with \r
and sometimes without. As a result, we have an occasional failure of
"runc run with tmpfs perms" test.
The solution (to the flaky test) is to use the first line of the output
(like many other tests do).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The original reasoning for this option was to avoid having mount options
be overwritten by runc. However, adding command-line arguments has
historically been a bad idea because it forces strict-runc-compatible
OCI runtimes to copy out-of-spec features directly from runc and these
flags are usually quite difficult to enable by users when using runc
through several layers of engines and orchestrators.
A far more preferable solution is to have a heuristic which detects
whether copying the original mount's mount options would override an
explicit mount option specified by the user. In this case, we should
return an error. You only end up in this path in the userns case, if you
have a bind-mount source with locked flags.
During the course of writing this patch, I discovered that several
aspects of our handling of flags for bind-mounts left much to be
desired. We have completely botched the handling of explicitly cleared
flags since commit 97f5ee4e6a ("Only remount if requested flags differ
from current"), with our behaviour only becoming increasingly more weird
with 50105de1d8 ("Fix failure with rw bind mount of a ro fuse") and
da780e4d27 ("Fix bind mounts of filesystems with certain options
set"). In short, we would only clear flags explicitly request by the
user purely by chance, in ways that it really should've been reported to
us by now. The most egregious is that mounts explicitly marked "rw" were
actually mounted "ro" if the bind-mount source was "ro" and no other
special flags were included. In addition, our handling of atime was
completely broken -- mostly due to how subtle the semantics of atime are
on Linux.
Unfortunately, while the runtime-spec requires us to implement
mount(8)'s behaviour, several aspects of the util-linux mount(8)'s
behaviour are broken and thus copying them makes little sense. Since the
runtime-spec behaviour for this case (should mount options for a "bind"
mount use the "mount --bind -o ..." or "mount --bind -o remount,..."
semantics? Is the fallback code we have for userns actually
spec-compliant?) and the mount(8) behaviour (see [1]) are not
well-defined, this commit simply fixes the most obvious aspects of the
behaviour that are broken while keeping the current spirit of the
implementation.
NOTE: The handling of atime in the base case is left for a future PR to
deal with. This means that the atime of the source mount will be
silently left alone unless the fallback path needs to be taken, and any
flags not explicitly set will be cleared in the base case. Whether we
should always be operating as "mount --bind -o remount,..." (where we
default to the original mount source flags) is a topic for a separate PR
and (probably) associated runtime-spec PR.
So, to resolve this:
* We store which flags were explicitly requested to be cleared by the
user, so that we can detect whether the userns fallback path would end
up setting a flag the user explicitly wished to clear. If so, we
return an error because we couldn't fulfil the configuration settings.
* Revert 97f5ee4e6a ("Only remount if requested flags differ from
current"), as missing flags do not mean we can skip MS_REMOUNT (in
fact, missing flags are how you indicate a flag needs to be cleared
with mount(2)). The original purpose of the patch was to fix the
userns issue, but as mentioned above the correct mechanism is to do a
fallback mount that copies the lockable flags from statfs(2).
* Improve handling of atime in the fallback case by:
- Correctly handling the returned flags in statfs(2).
- Implement the MNT_LOCK_ATIME checks in our code to ensure we
produce errors rather than silently producing incorrect atime
mounts.
* Improve the tests so we correctly detect all of these contingencies,
including a general "bind-mount atime handling" test to ensure that
the behaviour described here is accurate.
This change also inlines the remount() function -- it was only ever used
for the bind-mount remount case, and its behaviour is very bind-mount
specific.
[1]: https://github.com/util-linux/util-linux/issues/2433
Reverts: 97f5ee4e6a ("Only remount if requested flags differ from current")
Fixes: 50105de1d8 ("Fix failure with rw bind mount of a ro fuse")
Fixes: da780e4d27 ("Fix bind mounts of filesystems with certain options set")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Function teardown assumes that every test case will call
setup_sshfs. Currently, this assumption is true, but once
a test case that won't call setup_sshfs is added (say because
it has some extra "requires" or "skip"), it will break bats,
so any bats invocation involving such a test case will end up
hanging after the last test case is run.
The reason is, we have set -u in helpers.bash to help catching the use
of undefined variables. In the above scenario, such a variable is DIR,
which is referenced in teardown but is only defined after a call to
setup_sshfs. As a result, bash that is running the teardown function
will exit upon seeing the first $DIR, and thus teardown_bundle won't be
run. This, in turn, results in a stale recvtty process, which inherits
bats' fd 3. Until that fd is closed, bats waits for test logs.
Long story short, the fix is to
- check if DIR is set before referencing it;
- unset it after unmount.
PS it is still not clear why there is no diagnostics about the failed
teardown.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Commit e1584831b6 did two modifications to check_cgroup_value():
1. It now skips the test if the file is not found.
2. If the comparison failed, a second comparison, with value divided by 1000,
is performed.
These modifications were only needed for cpu.burst, but instead were done
in a generic function used from many cgroup tests. As a result, we can
no longer be sure about the test coverage (item 1) and the check being
correct (item 2) anymore. In fact, part of "update cgroup cpu limits"
test is currently skipped on CentOS 7 and 8 because of item 1.
To fix:
- replace item 1 with a new "cgroups_cpu_burst" argument for "requires",
and move the test to a separate case;
- replace item 2 with a local change in check_cpu_burst.
Fixes: e1584831b6
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This adds support for hugetlb.<pagesize>.rsvd limiting and accounting.
The previous non-rsvd max/limit_in_bytes does not account for reserved
huge page memory, making it possible for a processes to reserve all the
huge page memory, without being able to allocate it (due to cgroup
restrictions).
In practice this makes it possible to successfully mmap more huge page
memory than allowed via the cgroup settings, but when using the memory
the process will get a SIGBUS and crash. This is bad for applications
trying to mmap at startup (and it succeeds), but the program crashes
when starting to use the memory. eg. postgres is doing this by default.
This also keeps writing to the old max/limit_in_bytes, for backward
compatibility.
More info can be found here: https://lkml.org/lkml/2020/2/3/1153
(commit message mostly written by Odin Ugedal)
Co-authored-by: Odin Ugedal <odin@ugedal.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Bump fileutils to v0.5.1, which fixes permissions of newly created directories
to not depend on the value of umask.
Add a test case which fails like this before the fix:
mounts.bats
✗ runc run [tmpcopyup]
(in test file tests/integration/mounts.bats, line 28)
`[[ "${lines[0]}" == *'drwxrwxrwx'* ]]' failed
runc spec (status=0):
runc run test_busybox (status=0):
drwxr-xr-x 2 root root 40 Oct 4 22:35 /dir1/dir2
Fixes 3991.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Due to the way capabilities have to be set by runc, capabilities need to
be included in the inheritable and ambient sets anyway. Otherwise, the
container process would not have the correct privileges. This test only
functioned because adding CAP_DAC_OVERRIDE to the inherited,
permissible, and bounding sets means that only "runc init" has these
capabilities -- everything other than the bounding set is cleared on the
first execve(). This breaks with runc-dmz, but the behaviour was broken
from the outset.
Docker appears to not handle this properly at all (the logic for
capability sets changed with the introduction of ambient capabilities,
and while Docker was updated it seems the behaviour is still incorrect
for non-root users).
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Burstable CFS controller is introduced in Linux 5.14. This helps with
parallel workloads that might be bursty. They can get throttled even
when their average utilization is under quota. And they may be latency
sensitive at the same time so that throttling them is undesired.
This feature borrows time now against the future underrun, at the cost
of increased interference against the other system users, by introducing
cfs_burst_us into CFS bandwidth control to enact the cap on unused
bandwidth accumulation, which will then used additionally for burst.
The patch adds the support/control for CFS bandwidth burst.
runtime-spec: https://github.com/opencontainers/runtime-spec/pull/1120
Co-authored-by: Akihiro Suda <suda.kyoto@gmail.com>
Co-authored-by: Nadeshiko Manju <me@manjusaka.me>
Signed-off-by: Kailun Qin <kailun.qin@intel.com>
This file contains a test that tests .so hooks. It has a complicated
setup and teardown, and has special requirements (root and no_systemd).
Rename it to hooks_so.bats, so we can add hooks.bats for hooks tests
that do not have such complicated setup and requirements.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
When a hook has failed, the error message looks like this:
> error running hook: error running hook #1: exit status 1, stdout: ...
The two problems here are:
1. it is impossible to know what kind of hook it was;
2. "error running hook" stuttering;
Change that to
> error running createContainer hook #1: exit status 1, stdout: ...
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
These are not exhaustive, but at least confirm that the feature is not
obviously broken (we correctly set the time offsets).
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
The idea was to make them strict on dest path from the beginning for
idmap mounts, as runc would do that for all mounts in the future. But
that is causing too many problems.
For now, let's just allow relative paths for idmap mounts too. It just
seems safer.
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
This test fails in CI sometimes with the following error:
> `testcontainer test_update stopped' failed
Give OOM killer some time to do its job.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Currently bind mounts of filesystems with nodev, nosuid, noexec,
noatime, relatime, strictatime, nodiratime options set fail in rootless
mode if the same options are not set for the bind mount.
For ro filesystems this was resolved by #2570 by remounting again
with ro set.
Follow the same approach for nodev, nosuid, noexec, noatime, relatime,
strictatime, nodiratime but allow to revert back to the old behaviour
via the new `--no-mount-fallback` command line option.
Add a testcase to verify that bind mounts of filesystems with nodev,
nosuid, noexec, noatime options set work in rootless mode.
Add a testcase that mounts a nodev, nosuid, noexec, noatime filesystem
with a ro flag.
Add two further testcases that ensure that the above testcases would
fail if the `--no-mount-fallback` command line option is set.
* contrib/completions/bash/runc:
Add `--no-mount-fallback` command line option for bash completion.
* create.go:
Add `--no-mount-fallback` command line option.
* restore.go:
Add `--no-mount-fallback` command line option.
* run.go:
Add `--no-mount-fallback` command line option.
* libcontainer/configs/config.go:
Add `NoMountFallback` field to the `Config` struct to store
the command line option value.
* libcontainer/specconv/spec_linux.go:
Add `NoMountFallback` field to the `CreateOpts` struct to store
the command line option value and store it in the libcontainer
config.
* utils_linux.go:
Store the command line option value in the `CreateOpts` struct.
* libcontainer/rootfs_linux.go:
In case that `--no-mount-fallback` is not set try to remount the
bind filesystem again with the options nodev, nosuid, noexec,
noatime, relatime, strictatime or nodiratime if they are set on
the source filesystem.
* tests/integration/mounts_sshfs.bats:
Add testcases and rework sshfs setup to allow specifying
different mount options depending on the test case.
Signed-off-by: Ruediger Pluem <ruediger.pluem@vodafone.com>
runc ps requires cgroup, but all the tests but one required root. Let's
fix this.
1. Add rootless cgroup requirement to setup() to avoid repetition.
2. Add set_cgroups_path to setup() for rootless containers because
there is no default cgroup path.
3. Modify output checks to use $output rather than $lines because in case
of rootless the first line of output contains the following warning:
> runc ps may fail if you don't have the full access to cgroups
4. While at it, move the common part of every test (creating the
container and making sure it's running) to setup().
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The passing run (with the fix) looks like this:
----
delete.bats
✓ runc delete removes failed systemd unit [4556]
runc spec (status=0):
runc run -d --console-socket /tmp/bats-run-B08vu1/runc.lbQwU5/tty/sock test-failed-unit (status=0):
Warning: The unit file, source configuration file or drop-ins of runc-cgroups-integration-test-12869.scope changed on disk. Run 'systemctl daemon-reload' to reload units.
× runc-cgroups-integration-test-12869.scope - libcontainer container integration-test-12869
Loaded: loaded (/run/systemd/transient/runc-cgroups-integration-test-12869.scope; transient)
Transient: yes
Drop-In: /run/systemd/transient/runc-cgroups-integration-test-12869.scope.d
└─50-DevicePolicy.conf, 50-DeviceAllow.conf
Active: failed (Result: timeout) since Tue 2023-06-13 14:41:38 PDT; 751ms ago
Duration: 2.144s
CPU: 8ms
Jun 13 14:41:34 kir-rhat systemd[1]: Started runc-cgroups-integration-test-12869.scope - libcontainer container integration-test-12869.
Jun 13 14:41:37 kir-rhat systemd[1]: runc-cgroups-integration-test-12869.scope: Scope reached runtime time limit. Stopping.
Jun 13 14:41:38 kir-rhat systemd[1]: runc-cgroups-integration-test-12869.scope: Stopping timed out. Killing.
Jun 13 14:41:38 kir-rhat systemd[1]: runc-cgroups-integration-test-12869.scope: Killing process 1107438 (sleep) with signal SIGKILL.
Jun 13 14:41:38 kir-rhat systemd[1]: runc-cgroups-integration-test-12869.scope: Failed with result 'timeout'.
runc delete test-failed-unit (status=0):
Unit runc-cgroups-integration-test-12869.scope could not be found.
----
Before the fix, the test was failing like this:
----
delete.bats
✗ runc delete removes failed systemd unit
(in test file tests/integration/delete.bats, line 194)
`run -4 systemctl status "$SD_UNIT_NAME"' failed, expected exit code 4, got 3
....
----
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There is no such thing as linux.resources.memorySwap (the mem+swap is
set as linux.resources.memory.swap).
As it is not used in this test anyway, remove it.
Fixes: 4929c05ad1
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
When a directory already exists (or after a container is restarted) the
perms of the directory being mounted to were being used even when a
different permission is set on the tmpfs mount options.
This prepends the original directory perms to the mount options.
If the perms were already set in the mount opts then those perms will
win.
This eliminates the need to perform a chmod after mount entirely.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
We read output from the following files if they exists:
- cpu.pressure
- memory.pressure
- io.pressure
Each are in format:
```
some avg10=0.00 avg60=0.00 avg300=0.00 total=0
full avg10=0.00 avg60=0.00 avg300=0.00 total=0
```
Signed-off-by: Daniel Dao <dqminh89@gmail.com>
Co-authored-by: Sandor Szücs <sandor.szuecs@zalando.de>
Co-authored-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Rename CGROUP_PATH to CGROUP_V2_PATH so it is more clear that it can
only be used for CGROUP_V2, and to resolve ambiguity with CGROUP_PATH
variable used in tests/rootless.sh.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Filter out rdma controller since systemd is unable to delegate it.
Similar to commits 05272718f4 and 601cf5825f.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
As of previous commit, this is implied in a particular scenario. In
fact, this is the one and only scenario that justifies the use of -a.
Drop the option from the documentation. For backward compatibility, do
recognize it, and retain the feature of ignoring the "container is
stopped" error when set.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This is roughly the same as TestPIDHostInitProcessWait in libct/int,
except that here we use separate processes to create and to kill a
container, so the processes inside a container are not children of "runc kill", and
also we hit different codepaths (nonChildProcess.signal rather than
initProcess.signal).
One other thing is, rootless is also tested.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
It seems that set -x was temporarily added as a debug measure, but
slipped into the final commit.
Remove it, for the sake of test logs brevity.
Fixes: 9f656dbb11
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This test is occasionally failing on CS9.
The test case always takes about 7 seconds on my laptop (decreasing
memory, using a different memory eater in shell etc. doesn't help).
Increase the number of iterations from 10 to 30 to make sure we don't
see any flakes.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Apparently, bash with set -e deliberately ignores non-zero return codes
from ! cmd, unless this is the last command. The workaround is to either
use "! cmd || false', "or run ! cmd". Choose the latter, and require
bash-core 1.5.0 (since this is when "run !" was added), replacing the
older check.
Alas I only learned this recently from the bash-core documentation.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Systemd v252 (available in CentOS Stream 9 in our CI) added support
for setting cpu.idle (see [1]). The way it works is:
- if CPUWeight == 0, cpu.idle is set to 1;
- if CPUWeight != 0, cpu.idle is set to 0.
This commit implements setting cpu.idle in systemd cgroup driver via a
unit property. In case CPUIdle is set to non-zero value, the driver sets
adds CPUWeight=0 property, which will result in systemd setting cpu.idle
to 1.
Unfortunately, there's no way to set cpu.idle to 0 without also changing
the CPUWeight value, so the driver doesn't do anything if CPUIdle is
explicitly set to 0. This case is handled by the fs driver which is
always used as a followup to setting systemd unit properties.
Also, handle cpu.idle set via unified map. In case it is set to non-zero
value, add CPUWeight=0 property, and ignore cpu.weight (otherwise we'll
get two different CPUWeight properties set).
Add a unit test for new values in unified map, and an integration test case.
[1] https://github.com/systemd/systemd/pull/23299
[2] https://github.com/opencontainers/runc/issues/3786
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Values other than 1 or 0 are ignored by the kernel,
see sched_group_set_idle() in kernel/sched/fair.c
If the added test case ever fails, it means that the kernel now accepts
values other than 0 or 1, and runc needs to adopt to that.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Systemd v252 (available in CentOS Stream 9 in our CI) added support
for setting cpu.idle (see [1]). The way it works is:
- if CPUWeight == 0, cpu.idle is set to 1;
- if CPUWeight != 0, cpu.idle is set to 0.
This behavior breaks the existing test case, as described in [2].
To fix, skip the last check in the test case in case a newer systemd
is used.
Fixes: #3786
[1] https://github.com/systemd/systemd/pull/23299
[2] https://github.com/opencontainers/runc/issues/3786
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
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>
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>