Commit Graph

2567 Commits

Author SHA1 Message Date
Aleksa Sarai 1f25724a96 configs: fix idmapped mounts json field names
In the runc state JSON we always use snake_case. This is a no-op change,
but it will cause any existing container state files to be incorrectly
parsed. Luckily, commit fbf183c6f8 ("Add uid and gid mappings to
mounts") has never been in a runc release so we can change this before a
1.2.z release.

Fixes: fbf183c6f8 ("Add uid and gid mappings to mounts")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-15 19:54:24 -07:00
Aleksa Sarai 8aa97ad3a3 nsexec: remove cgroupns special-casing
The original implementation of cgroupns had additional synchronisation
to "ensure" that the process is in the correct cgroup before unsharing
the cgroupns. This behaviour was actually never necessary, and after
commit 5110bd2fc0 ("nsenter: remove cgroupns sync mechanism") there is
no synchronisation at all, meaning that CLONE_NEWCGROUP should not get
any special treatment.

Fixes: 5110bd2fc0 ("nsenter: remove cgroupns sync mechanism")
Fixes: df3fa115f9 ("Add support for cgroup namespace")
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-15 19:54:24 -07:00
Aleksa Sarai 5c7839b503 rootfs: use empty src for MS_REMOUNT
The kernel ignores these arguments, and passing them can lead to
confusing error messages (the old source is irrelevant for MS_REMOUNT),
as well as causing issues for a future patch where we switch to
move_mount(2).

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-15 19:54:24 -07:00
Aleksa Sarai 20b95f23ca libcontainer: seccomp: pass around *os.File for notifyfd
*os.File is correctly tracked by the garbage collector, and there's no
need to use raw file descriptors for this code.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-15 19:54:24 -07:00
Aleksa Sarai f81ef1493d libcontainer: sync: cleanup synchronisation code
This includes quite a few cleanups and improvements to the way we do
synchronisation. The core behaviour is unchanged, but switching to
embedding json.RawMessage into the synchronisation structure will allow
us to do more complicated synchronisation operations in future patches.

The file descriptor passing through the synchronisation system feature
will be used as part of the idmapped-mount and bind-mount-source
features when switching that code to use the new mount API outside of
nsexec.c.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-15 19:54:24 -07:00
Kir Kolyshkin c6e7b1a8ec libct: initProcess.start: fix sync logic
The code in this function became quite complicated and not entirely
correct over time. As a result, if an error is returned from parseSync,
it might end up stuck waiting for the child to finish.

1. Let's not wait() for the child twice. We already do it in the
defer statement (call p.terminate()) when we are returning an error.

2. Remove sentResume and sentRun since we do not want to check if
these were sent or not. Instead, introduce and check seenProcReady, as
procReady is always expected from runc init.

3. Eliminate the possibility to wrap nil as an error.

4. Make sure we always call shutdown on the sync socket, and do not let
   shutdown error shadow the ierr.

This fixes the issue of stuck `runc runc` with the optimization patch
(sending procSeccompDone earlier) applied.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-15 19:54:24 -07:00
Aleksa Sarai aa5f4c1137 tests: add several timens tests
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>
2023-08-10 19:01:31 +10:00
Aleksa Sarai 9acfd7b1a3 timens: minor cleanups
Fix up a few things that were flagged in the review of the original
timens PR, namely around error handling and validation.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-10 18:59:55 +10:00
Aleksa Sarai 0866112e81 merge #3876 into opencontainers/runc:main
Chethan Suresh (1):
  Support time namespace

LGTMs: kolyskin cyphar
Closes #3876
2023-08-10 18:27:17 +10:00
Kir Kolyshkin cb44958162 Merge pull request #3385 from kolyshkin/init-logger-setup
init simplification
2023-08-08 19:05:02 -07:00
Rodrigo Campos ec2ffae5f1 libct: Allow rel paths for idmap mounts
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>
2023-08-08 13:45:31 +02:00
Rodrigo Campos 19d26a6596 Revert "libct/validator: Error out on non-abs paths"
This reverts commit 881e92a3fd and adjust
the code so the idmap validations are strict.

We now only throw a warning and the container is started just fine.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-08-08 13:45:31 +02:00
lfbzhm acab6f6416 Merge pull request #3931 from cyphar/remove-bindfd
nsexec: cloned_binary: remove bindfd logic entirely
2023-08-05 23:38:44 +08:00
Kir Kolyshkin 883aef789b libct/init: unify init, fix its error logic
This commit does two things:

1. Consolidate StartInitialization calling logic into Init().
2. Fix init error handling logic.

The main issues at hand are:
- the "unable to convert _LIBCONTAINER_INITPIPE" error from
  StartInitialization is never shown;
- errors from WriteSync and WriteJSON are never shown;
- the StartInit calling code is triplicated;
- using panic is questionable.

Generally, our goals are:
 - if there's any error, do our best to show it;
 - but only show each error once;
 - simplify the code, unify init implementations.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-04 13:00:35 -07:00
Kir Kolyshkin 789a73db22 init.go: move logger setup to StartInitialization
Currently, logrus is used from the Go part of runc init, mostly for a
few debug messages (see setns_init_linux.go and standard_init_linux.go),
and a single warning (see rootfs_linux.go).

This means logrus is part of init implementation, and thus, its setup
belongs to StartInitialization().

Move the code there. As a nice side effect, now we don't have to convert
_LIBCONTAINER_LOGPIPE twice.

Note that since this initialization is now also called from libct/int
tests, which do not set _LIBCONTAINER_LOGLEVEL, let's make
_LIBCONTAINER_LOGLEVEL optional.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-04 13:00:34 -07:00
Aleksa Sarai 0d890ad66f nsenter: cloned_binary: use MFD_EXEC and F_SEAL_EXEC
With the new vm.memfd_noexec sysctl, we need to make sure we explicitly
request MFD_EXEC, otherwise an admin could inadvertently break
containers in a somewhat-annoying-to-debug fashion.

It should be noted that vm.memfd_noexec=2 is broken on Linux 6.4
(MFD_EXEC works even in the most restrictive mode) and the most severe
breakage is going to be fixed in Linux 6.6[1].

[1]: https://lore.kernel.org/20230705063315.3680666-2-jeffxu@google.com/

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-04 23:39:36 +10:00
Aleksa Sarai b999376fb2 nsenter: cloned_binary: remove bindfd logic entirely
While the ro-bind-mount trick did eliminate the memory overhead of
copying the runc binary for each "runc init" invocation, on machines
with very significant container churn, creating a temporary mount
namespace on every container invocation can trigger severe lock
contention on namespace_sem that makes containers fail to spawn.

The only reason we added bindfd in commit 16612d74de ("nsenter:
cloned_binary: try to ro-bind /proc/self/exe before copying") was due to
a Kubernetes e2e test failure where they had a ridiculously small memory
limit. It seems incredibly unlikely that real workloads are running
without 10MB to spare for the very short time that runc is interacting
with the container.

In addition, since the original cloned_binary implementation, cgroupv2
is now almost universally used on modern systems. Unlike cgroupv1, the
cgroupv2 memcg implementation does not migrate memory usage when
processes change cgroups (even cgroupv1 only did this if you had
memory.move_charge_at_immigrate enabled). In addition, because we do the
/proc/self/exe clone before synchronising the bootstrap data read, we
are guaranteed to do the clone before "runc init" is moved into the
container cgroup -- meaning that the memory used by the /proc/self/exe
clone is charged against the root cgroup, and thus container workloads
should not be affected at all with memfd cloning.

The long-term fix for this problem is to block the /proc/self/exe
re-opening attack entirely in-kernel, which is something I'm working
on[1]. Though it should also be noted that because the memfd is
completely separate to the host binary, even attacks like Dirty COW
against the runc binary can be defended against with the memfd approach.
Of course, once we have in-kernel protection against the /proc/self/exe
re-opening attack, we won't have that protection anymore...

[1]: https://lwn.net/Articles/934460/

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-04 14:49:05 +10:00
Kir Kolyshkin 38676931ed criu: do not add log file into error message
As we now log the log file name in logCriuErrors.

While at it, there is no need to use var.String() with %s as it is done
by the runtime.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-03 10:39:33 -07:00
Kir Kolyshkin c77aaa3f95 criu checkpoint/restore: print errors from criu log
When criu fails, it does not give us much context to understand what
was the cause of an error -- for that, we need to take a look into its
log file.

This is somewhat complicated to do (as you can see in parts of
checkpoint.bats removed by this commit), and not very user-friendly.

Add a function to find and log errors from criu logs, together with some
preceding context, in case either checkpoint or restore has failed.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-03 10:33:20 -07:00
Kir Kolyshkin e4478e9fff criuSwrk: simplify switch
1. Use "switch t" since we only check t.

2. Remove unneeded t assignment.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-03 10:33:20 -07:00
Kir Kolyshkin cb981e510b libct: move criu-related stuff to separate file
No code change, only added periods to some comments to make godot happy.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-03 10:16:01 -07:00
Kir Kolyshkin 5c6b334c88 ci: fix TestOpenat2 when no systemd is used
A few cases relied on the fact that systemd is used, and thus
/sys/fs/cgroup/user.slice is available.

Guess what, in case of "make unittest" it might not be.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-02 23:00:46 -07:00
Kir Kolyshkin 962019d64e ci: fix TestNilResources when systemd not available
Split the test into two -- for fs and systemd cgroup managers, and only
run the second one if systemd is available.

Prevents the following failure during `make unittest`:

> === RUN   TestNilResources
>     manager_test.go:27: systemd not running on this host, cannot use systemd cgroups manager
> --- FAIL: TestNilResources (0.22s)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-08-02 23:00:46 -07:00
Akihiro Suda f0a5e6b96f Merge pull request #3930 from cyphar/close_range
utils: use close_range(2) to close leftover file descriptors
2023-08-03 14:58:15 +09:00
Kir Kolyshkin 2da710ca2f Merge pull request #3933 from alexeldeib/ace/v2root
libct/cg/fs2: use file + anon + swap for usage
2023-08-02 22:30:13 -07:00
Chethan Suresh ebc2e7c435 Support time namespace
"time" namespace was introduced in Linux v5.6
support new time namespace to set boottime and monotonic time offset

Example runtime spec

"timeOffsets": {
    "monotonic": {
        "secs": 172800,
        "nanosecs": 0
    },
    "boottime": {
        "secs": 604800,
        "nanosecs": 0
    }
}

Signed-off-by: Chethan Suresh <chethan.suresh@sony.com>
2023-08-03 10:12:01 +05:30
lifubang 6092a4b42d fix some file mode bits missing when doing mount syscall
Signed-off-by: lifubang <lifubang@acmcoder.com>
2023-08-03 08:44:00 +08:00
Alexander Eldeib 7d2becdf2c libct/cg/fs2: use file + anon + swap for usage
This aligns v2 usage calculations more closely with v1.
Current node-level reporting for v1 vs v2 on the same
machine under similar load may differ by ~250-750Mi.

Also return usage as combined swap + memory usage, aligned
with v1 and non-root v2 cgroups.

`mem_cgroup_usage` in the kernel counts NR_FILE_PAGES
+ NR_ANON_MAPPED + `nr_swap_pages` (if swap enabled) [^0].

Using total - free results in higher "usage" numbers.
This is likely due to various types of reclaimable
memory technically counted as in use (e.g. inactive anon).

See also https://github.com/kubernetes/kubernetes/issues/118916 for more context

[^0]: https://github.com/torvalds/linux/blob/06c2afb862f9da8dc5efa4b6076a0e48c3fbaaa5/mm/memcontrol.c#L3673-L3680

Signed-off-by: Alexander Eldeib <alexeldeib@gmail.com>
2023-08-02 15:18:22 +02:00
Aleksa Sarai 70f4e46e68 utils: use close_range(2) to close leftover file descriptors
close_range(2) is far more efficient than a readdir of /proc/self/fd and
then doing a syscall for each file descriptor.

Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2023-08-01 15:37:58 +10:00
Kir Kolyshkin dbe8434359 Merge pull request #3949 from kinvolk/rata/idmap-improve-errors
libct/nsenter: Show better errors for idmap mounts
2023-07-31 17:27:35 -07:00
Rodrigo Campos 57f31c68dc libct/nsenter: Show better errors for idmap mounts
While testing this with old kernel versions and kernels that don't
support idmap mounts for some of the filesystems used by a container, I
realized we can throw a more clear errors.

Let's make it clear which syscall we are using, when it is not supported
and when if the fs doesn't support idmap mounts, which path it is.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-31 13:44:37 +02:00
Kir Kolyshkin 701dff798d libct/cg/sd: use systemd v240+ new MAJOR:* syntax
Since systemd v240 (commit 8e8b5d2e6d91180a), one can use
/dev/{char,block}-MAJOR syntax to specify that all MAJOR:*
devices are allowed.

Use it, if available, since it's more straightforward, plus
we can skip somewhat expensive parsing of /proc/devices.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-07-29 22:41:05 +08:00
Ruediger Pluem da780e4d27 Fix bind mounts of filesystems with certain options set
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>
2023-07-28 16:32:02 -07:00
lifubang c875ea8529 use the length of UIDMappings/GIDMappings to check whether empty or not
Signed-off-by: lifubang <lifubang@acmcoder.com>
2023-07-23 11:59:18 +08:00
Francis Laniel a3785c88ec Remove idmapFD field for mountEntry
We cannot have both srcFD and idMapFD set at the same time.
So, we can simplify this struct to only have one field which is used a srcFD
most of the time and as idMapFD when we do an id map mount.

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
2023-07-21 13:55:34 +02:00
Francis Laniel 46ada59ba2 Use an *int for srcFD
Previously to this commit, we used a string for srcFD as /proc/self/fd/NN.
This commit modified to this behavior, so srcFD is only an *int and the full path
is constructed in mountViaFDs() if srcFD is different than nil.

Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
2023-07-21 13:55:34 +02:00
Francis Laniel c47f58c4e9 Capitalize [UG]idMappings as [UG]IDMappings
Signed-off-by: Francis Laniel <flaniel@linux.microsoft.com>
2023-07-21 13:55:34 +02:00
lfbzhm f73b05dee6 Merge pull request #3717 from kinvolk/rata/idmap
Support idmap mounts for volumes
2023-07-17 21:55:50 +08:00
Rodrigo Campos fda12ab101 Support idmap mounts on volumes
This commit adds support for idmap mounts as specified in the runtime-spec.

We open the idmap source paths and call mount_setattr() in runc PARENT,
as we need privileges in the init userns for that, and then sends the
fds to the child process. For this fd passing we use the same mechanism
used in other parts of thecode, the _LIBCONTAINER_ env vars.

The mount is finished (unix.MoveMount) from go code, inside the userns,
so we reuse all the prepareBindMount() security checks and the remount
logic for some flags too.

This commit only supports idmap mounts when userns are used AND the mappings
are the same specified for the userns mapping. This limitation is to
simplify the initial implementation, as all our users so far only need
this, and we can avoid sending over netlink the mappings, creating a
userns with this custom mapping, etc. Future PRs will remove this
limitation.

Co-authored-by: Francis Laniel <flaniel@linux.microsoft.com>
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-17 13:30:12 +02:00
Kir Kolyshkin 98317c16ed ci: bump golangci-lint, remove fixed exception
The exception was fixed by https://github.com/polyfloyd/go-errorlint/pull/12
which eventually made its way into golangci-lint.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2023-07-16 15:02:26 +08:00
lfbzhm caa6e523f2 Merge pull request #3900 from kolyshkin/psi
libct/cg/stats: support PSI for cgroup v2
2023-07-14 09:06:31 +08:00
Rodrigo Campos fe4528b176 libcontainer: Just print the mountFds slice len on errors
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 73b649705a libcontainer: Add mountFds struct
We will need to pass more slices of fds to these functions in future
patches. Let's add a struct that just contains them all, instead of
adding lot of parameters to these functions.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 0172016a53 libcontainer: Add generic parseFdsFromEnv()
We will add code that uses this function in future patches. So let's
just split it to a new function now and reuse it later.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos f5814a1007 libcontainer: Add generic sendFdsSources()
Let's move the code to send mount sources to a generic function. Future
patches will use it for idmap sources too.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 96bd487590 nsenter: Add idmap helpers
We add idmap.h with the needed includes and defines in case the system
headers don't have the definition for the idmap syscalls we need.

Future patches will use these helpers.

Co-authored-by: Francis Laniel <flaniel@linux.microsoft.com>
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 5166164ded nsexec: Add generic receive_sources()
Future patches will use this with another env var.

Co-authored-by: Francis Laniel <flaniel@linux.microsoft.com>
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 4b668a8224 Switch setupUserNamespace() to use the toConfigIDMap() helper
We just added this helper for other parts of the code, let's switch this
function to use the helper too.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos fbf183c6f8 Add uid and gid mappings to mounts
Co-authored-by: Francis Laniel <flaniel@linux.microsoft.com>
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-11 16:17:48 +02:00
Rodrigo Campos 881e92a3fd libct/validator: Error out on non-abs paths
This was a warning already and it was requested to make this an error
while we will add validation of idmap mounts:
	https://github.com/opencontainers/runc/pull/3717#discussion_r1154705318

I've also tested a k8s cluster and the config.json generated by
containerd didn't use any relative paths. I tested one pod, so it was
definitely not an extensive test.

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
2023-07-07 12:00:33 +02:00