2314 Commits

Author SHA1 Message Date
Kir Kolyshkin c0e300f109 Refuse to build runc without nsenter
Commit 4d1d6185ab added this
nsenter_unsupported.go file in order for nsenter to be a valid (but
empty, non-functional) Go package on unsupported platforms.

As a result, runc can be build successfully without CGO, which results
in a non-working and hard-to-debug binary (see issue 3330).

As the functionality of being able to compile a package which is
definitely not working is questionable, and I can't think of any use
cases, let's remove the file.

With this, runc can no longer be build without CGO:

	[kir@kir-rhat runc]$ CGO_ENABLED=0 make runc
	go build -trimpath "-buildmode=pie"  -tags "seccomp" -ldflags "-X main.gitCommit=v1.0.0-452-g00f56786-dirty -X main.version=1.1.0-rc.1+dev " -o runc .
	go build github.com/opencontainers/runc/libcontainer/nsenter: build constraints exclude all Go files in /home/kir/go/src/github.com/opencontainers/runc/libcontainer/nsenter

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2022-01-04 15:49:41 -08:00
Kir Kolyshkin 5c7e898186 libct/cg: rm go 1.15 compatibility
Since commit 12e99a0f8d we do require Go >= 1.16, so this file
is no longer needed.

Also, this actually ensures that go >= 1.16 is used (otherwise
libcontainer/cgroups/getallpids.go won't compile).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-12-14 13:08:47 -08:00
Aleksa Sarai 7e792c9236 merge branch 'pr-3301'
Kir Kolyshkin (1):
  libct/utils: ResolveRootfs: remove

LGTMs: AkihiroSuda cyphar
Closes #3301
2021-12-09 23:11:12 +11:00
Akihiro Suda 382eba4354 Support recursive mount attrs ("rro", "rnosuid", "rnodev", ...)
The new mount option "rro" makes the mount point recursively read-only,
by calling `mount_setattr(2)` with `MOUNT_ATTR_RDONLY` and `AT_RECURSIVE`.
https://man7.org/linux/man-pages/man2/mount_setattr.2.html

Requires kernel >= 5.12.

The "rro" option string conforms to the proposal in util-linux/util-linux Issue 1501.

Fix issue 2823

Similary, this commit also adds the following mount options:
- rrw
- r[no]{suid,dev,exec,relatime,atime,strictatime,diratime,symfollow}

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2021-12-07 17:39:57 +09:00
Akihiro Suda ba935a51a6 Support nosymfollow mount option (kernel 5.10)
See MS_NOSYMFOLLOW in mount(2)

https://man7.org/linux/man-pages/man2/mount.2.html

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2021-12-07 17:33:49 +09:00
Aleksa Sarai cdce249635 merge branch 'pr-3057'
Fraser Tweedale (1):
  chown cgroup to process uid in container namespace

LGTMs: kolyshkin cyphar
Closes #3057
2021-12-07 17:06:19 +11:00
Aleksa Sarai 2b0ca195d6 merge branch 'pr-3296'
Akihiro Suda (1):
  Add `runc features` command

LGTMs: kolyshkin cyphar
Closes #3296
2021-12-07 16:15:37 +11:00
Aleksa Sarai f50369af4b Merge pull request from GHSA-v95c-p5hm-xq8f
runc init: avoid netlink message length overflows
2021-12-06 15:30:29 +11:00
Aleksa Sarai d72d057ba7 runc init: avoid netlink message length overflows
When writing netlink messages, it is possible to have a byte array
larger than UINT16_MAX which would result in the length field
overflowing and allowing user-controlled data to be parsed as control
characters (such as creating custom mount points, changing which set of
namespaces to allow, and so on).

Co-authored-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2021-12-03 16:07:40 +11:00
Kir Kolyshkin 25112dd179 libct/intelrdt: remove unused type
Since commit 7296dc1712, type intelRdtData is only used by tests,
and since commit 79d292b9f, its only member is config.

Change the test to use config directly, and remove the type.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-30 18:03:28 -08:00
Akihiro Suda 520702dac5 Add runc features command
Fix issue 3274

See `types/features/features.go`.

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2021-11-30 16:40:39 +09:00
Kir Kolyshkin 953e56c56f libct/int: runContainer: drop console arg
It is not and was never ever used.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin 6c0bfcb1c8 libct/cg/fs/blkio_test: ignore unparam warning
Ignore the following warning:

> libcontainer/cgroups/fs/blkio_test.go:167:78: `appendBlkioStatEntry` - `minor` always receives `0` (unparam)
> func appendBlkioStatEntry(blkioStatEntries *[]cgroups.BlkioStatEntry, major, minor, value uint64, op string) {

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin 06b3fd9d19 libct/cg/ebpf: drop finalize return value
It never returns any error, so let's drop it (in case it needs to be
re-added, it is easy to do so).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin 741568ebf1 libct/cg/devices: addRule: ignore unparam warning
This function has a return value for consistency, let it stay.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin dd14040145 libct: fixStdioPermissions: rm config arg
Since commit ff5075c33f it is no longer used.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin b357bc1349 libct/factory: rm id param from loadState
It is not used since commit e918d0213.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 20:10:22 -08:00
Kir Kolyshkin b950b778c2 libct/utils: ResolveRootfs: remove
Since commit 8850636eb3 (February 2015) this function is no longer
used (replaced by (*ConfigValidator).rootfs), so let's remove it,
together with its unit tests (which were added by commit 917c1f6d6 in
April 2016).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-29 19:21:26 -08:00
Fraser Tweedale 35d20c4e0b chown cgroup to process uid in container namespace
Delegating cgroups to the container enables more complex workloads,
including systemd-based workloads.  The OCI runtime-spec was
recently updated to explicitly admit such delegation, through
specification of cgroup ownership semantics:

  https://github.com/opencontainers/runtime-spec/pull/1123

Pursuant to the updated OCI runtime-spec, change the ownership of
the container's cgroup directory and particular files therein, when
using cgroups v2 and when the cgroupfs is to be mounted read/write.

As a result of this change, systemd workloads can run in isolated
user namespaces on OpenShift when the sandbox's cgroupfs is mounted
read/write.

It might be possible to implement this feature in other cgroup
managers, but that work is deferred.

Signed-off-by: Fraser Tweedale <ftweedal@redhat.com>
2021-11-30 08:52:59 +10:00
Akihiro Suda 6ff042023c Merge pull request #3234 from kolyshkin/hugepage-v2
libct/cg: refactor/improve/rename GetHugePageSize -> HugePageSizes
2021-11-29 18:14:14 +09:00
Aleksa Sarai 19d696ec29 merge branch 'pr-3276'
Kir Kolyshkin (2):
  runc run: fix ro /dev
  test/int/mount.bats: refer to github issue

LGTMs: thaJeztah cyphar
Closes #3276
2021-11-26 09:37:43 +11:00
Kir Kolyshkin ec0f35bc68 libct/system/xattrs: remove
This is not used since commit 5e7b48f7c0 (23 Mar 2017).

In case there are external users, they should switch to
opencontainers/selinux.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-23 08:40:49 -08:00
Sebastiaan van Stijn 02fe5f4734 Merge pull request #3283 from kolyshkin/rootless-ro-bind-rw
Fix failure with rw bind mount of a ro fuse
2021-11-22 18:39:44 +01:00
Kir Kolyshkin 1da84d1aff libct/cg: TestGetHugePageSizeImpl: use t.Run
Move test case comments to doc strings, and use t.Run.

Suggested-by:  Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-19 12:03:12 -08:00
Dave Chen 1362291a6d Avoid non-op when the list of Hooks is empty
There is no need to run hooks when `Config.Hooks` is just an empty map,

(dlv) p p.config.Config.Hooks
github.com/opencontainers/runc/libcontainer/configs.Hooks []

Signed-off-by: Dave Chen <dave.chen@arm.com>
2021-11-19 22:37:27 +08:00
Akihiro Suda eba6097aba Merge pull request #3287 from cyphar/netlink-embedded-nulls
specconv: do not permit null bytes in mount fields
2021-11-19 14:06:59 +09:00
Kir Kolyshkin f13a932570 libct/cg: HugePageSizes: simplify code and test
1. Instead of distinguishing between errors and warnings, let's treat all
   errors as warnings, thus simplifying the code. This changes the
   function behaviour for input like hugepages-BadNumberKb --
   previously, the error from Atoi("BadNumber") was considered fatal,
   now it's just another warnings.

2. Move the warning logging to HugePageSizes, thus simplifying the test
   case, which no longer needs to read what logrus writes. Note that we
   do not want to log all the warnings (as chances are very low we'll
   get any, and if we do this means the code need to be updated), only
   the first one.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-18 18:20:49 -08:00
Kir Kolyshkin 39d4c8d5f9 libct/cg: lazy init for HugePageSizes
I have noticed that libct/cg/fs allocates 8K during init on every runc
execution:

> init github.com/opencontainers/runc/libcontainer/cgroups/fs @1.5 ms, 0.028 ms clock, 8512 bytes, 13 allocs

Apparently this is caused by global HugePageSizes variable init, which
is only used from GetStats (i.e. it is never used by runc itself).

Remove it, and use HugePageSizes() directly instead. Make it init-once,
so that GetStats (which, I guess, is periodically called by kubernetes)
does not re-read huge page sizes over and over.

This also removes 12 allocs and 8K from libct/cg/fs init section:

> $ time GODEBUG=inittrace=1 ./runc --help 2>&1 | grep cgroups/fs
> init github.com/opencontainers/runc/libcontainer/cgroups/fs @1.5 ms, 0.003 ms clock, 16 bytes, 1 allocs

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-18 18:20:49 -08:00
Kir Kolyshkin a4d4c4dd9f libct/cg: GetHugePageSize -> HugePageSizes
1. Since GetHugePageSize do not have any external users (checked by
   sourcegraph), and no internal user ever uses its second return value
   (the error), let's drop it.

2. Rename GetHugePageSize -> HugePageSizes (drop the Get prefix as per
   Go guidelines, add suffix since we return many sizes).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-18 18:20:49 -08:00
Aleksa Sarai dde509df4e specconv: do not permit null bytes in mount fields
Using null bytes as control characters for sending strings via netlink
opens us up to a user explicitly putting a null byte in a mount string
(which JSON will happily let you do) and then causing us to open a mount
path different to the one expected.

In practice this is more of an issue in an environment such as
Kubernetes where you may have path-based access control policies (which
are more susceptible to these kinds of flaws).

Found by Google Project Zero.

Fixes: 9c444070ec ("Open bind mount sources from the host userns")
Reported-by: Felix Wilhelm <fwilhelm@google.com>
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
2021-11-19 11:41:05 +11:00
Kir Kolyshkin 50105de1d8 Fix failure with rw bind mount of a ro fuse
As reported in [1], in a case where read-only fuse (sshfs) mount
is used as a volume without specifying ro flag, the kernel fails
to remount it (when adding various flags such as nosuid and nodev),
returning EPERM.

Here's the relevant strace line:

> [pid 333966] mount("/tmp/bats-run-PRVfWc/runc.RbNv8g/bundle/mnt", "/proc/self/fd/7", 0xc0001e9164, MS_NOSUID|MS_NODEV|MS_REMOUNT|MS_BIND|MS_REC, NULL) = -1 EPERM (Operation not permitted)

I was not able to reproduce it with other read-only mounts as the source
(tried tmpfs, read-only bind mount, and an ext2 mount), so somehow this
might be specific to fuse.

The fix is to check whether the source has RDONLY flag, and retry the
remount with this flag added.

A test case (which was kind of hard to write) is added, and it fails
without the fix. Note that rootless user need to be able to ssh to
rootless@localhost in order to sshfs to work -- amend setup scripts
to make it work, and skip the test if the setup is not working.

[1] https://github.com/containers/podman/issues/12205

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-18 13:09:41 -08:00
Kir Kolyshkin 982b9a1dd3 libct/standard_init: fix linter warning
The staticcheck linter points out that the err != nil comparison
after system.Exec is always true:

> libcontainer/standard_init_linux.go#L253
> SA4023: this comparison is always true (staticcheck)
> libcontainer/system/linux.go#L43
> SA4023(related information): github.com/opencontainers/runc/libcontainer/system.Exec never returns a nil interface value (staticcheck)

Indeed, Exec either returns an error or does not return at all.

Remove the (useless) check.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-18 08:53:50 -08:00
Kir Kolyshkin 643f8a2b40 libct/specconv: nits
1. Decapitalize errors.
2. Rename isValidName to checkPropertyName.
3. Make it return a specific error.

Suggested-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-17 17:32:28 -08:00
Sebastiaan van Stijn 20e928875a Merge pull request #3275 from kolyshkin/rm-prlimit
libcontainer/system: rm Prlimit
2021-11-17 14:38:27 +01:00
Sebastiaan van Stijn e49007f3ad Merge pull request #3281 from kolyshkin/specconv-maps
libct/specconv: reduce init allocations, use global maps, refactor
2021-11-17 13:40:59 +01:00
Kir Kolyshkin b247cd392a runc run: fix ro /dev
Commit fb4c27c4b7 (went into v1.0.0-rc93) fixed a bug with
read-only tmpfs, but introduced a bug with read-only /dev.

This happens because /dev is a tmpfs mount and is therefore remounted
read-only a bit earlier than before.

To fix,

1. Revert the part of the above commit which remounts all tmpfs mounts
   as read-only in mountToRootfs.

2. Reuse finalizeRootfs (which is already used to remount /dev
   read-only) to also remount all ro tmpfs mounts that were previously
   mounted rw in mountPropagate.

3. Remove the break in finalizeRootfs, as now we have more than one
   mount to care about.

4. Reorder the if statements in finalizeRootfs to perform the fast check
   (for ro flag) first, and compare the strings second. Since /dev is
   most probably also a tmpfs mount, do the m.Device check first.

Add a test case to validate the fix and prevent future regressions;
make sure it fails before the fix:

 ✗ runc run [ro /dev mount]
   (in test file tests/integration/mounts.bats, line 45)
     `[ "$status" -eq 0 ]' failed
   runc spec (status=0):

   runc run test_busybox (status=1):
   time="2021-11-12T12:19:48-08:00" level=error msg="runc run failed: unable to start container process: error during container init: error mounting \"devpts\" to rootfs at \"/dev/pts\": mkdir /tmp/bats-run-VJXQk7/runc.0Fj70w/bundle/rootfs/dev/pts: read-only file system"

Fixes: fb4c27c4b7
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-15 10:37:16 -08:00
Kir Kolyshkin 029b73c1b0 libct/spec: replace isValidName regex with a function
Also, add a simple test and a benchmark (just out of sheer curiosity).

Benchmark results:

name           old time/op  new time/op  delta
IsValidName-4   540ns ± 3%    45ns ± 1%  -91.76%  (p=0.008 n=5+5)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:23:49 -08:00
Kir Kolyshkin 6907becaf9 libct/specconv: remove isSecSuffix regex
Commit 1cd71dfd7 added isSecSuffix, but the same thing can be done
easily without a regex. This is faster and saves some init time and
memory.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:23:47 -08:00
Kir Kolyshkin 37c5fd554e libct/specconv: make parseMountOptions return Mount
parseMountOption already returns way too many values, making the code
kind of hard to read.

Since all of the return values are used as is to populate the fields of
configs.Mount, let's change it to return (semi-)populated *configs.Mount
instead.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:23:30 -08:00
Kir Kolyshkin 2c3792baf9 libct/specconv: make mountFlags and extensionFlags global
This makes the repeated calls to parseMountOptions faster,
and decreases the amount of garbage to collect.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:16:04 -08:00
Kir Kolyshkin 81586e1935 libct/specconv: reuse mountPropagationMapping in parseMountOptions
These two maps are the same, except that mountPropagationMapping
has an extra element with key of "" and value of 0. Since the
code already checks for f != 0, this extra element is not a problem.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:15:54 -08:00
Kir Kolyshkin 8fe1e8bf8c libct/specconv: rm some init allocations
Eliminate some of these allocations when starting runc:

> init github.com/opencontainers/runc/libcontainer/specconv @10 ms, 0.11 ms clock, 5408 bytes, 70 allocs

Most of this (4K) is the two regexes, which are left intact for now.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 20:15:37 -08:00
Kir Kolyshkin 7563a8f06d libct: wrap more unix errors
When I tried to start a rootless container under a different/wrong user,
I got:

	$ ../runc/runc --systemd-cgroup --root /tmp/runc.$$ run 445
	ERRO[0000] runc run failed: operation not permitted

This is obviously not good enough. With this commit, the error is:

	ERRO[0000] runc run failed: fchown fd 9: operation not permitted

Alas, there are still some code that returns unwrapped errnos from
various unix calls.

This is a followup to commit d8ba4128b2 which wrapped many, but not
all, bare unix errors. Do wrap some more, using either os.PathError or
os.SyscallError.

While at it,
 - use os.SyscallError instead of os.NewSyscallError;
 - use errors.Is(err, os.ErrXxx) instead of os.IsXxx(err).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-12 00:33:59 -08:00
Kir Kolyshkin db4ad6a7f1 libcontainer/system: rm Prlimit
It is now available from golang.org/x/sys/unix
(https://go-review.googlesource.com/c/sys/+/332029)

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-11 19:57:56 -08:00
Akihiro Suda cbd725e6ef Merge pull request #3223 from kolyshkin/refuse-bad-cgroup
run create/run/exec: refuse bad cgroup
2021-11-08 16:19:43 +09:00
Mengjiao Liu a9bb11ec3c Fix the conversion of sysctl variable dots and slashes
Signed-off-by: Mengjiao Liu <mengjiao.liu@daocloud.io>
2021-11-04 11:45:15 +08:00
Mengjiao Liu 0f933d54fe Rename package validate_test to package validate
Signed-off-by: Mengjiao Liu <mengjiao.liu@daocloud.io>
2021-11-04 11:45:15 +08:00
Kir Kolyshkin 68c2b6a7d9 runc run: refuse a frozen cgroup
Sometimes a container cgroup already exists but is frozen.
When this happens, runc init hangs, and it's not clear what is going on.

Refuse to run in a frozen cgroup; add a test case.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-03 20:36:27 -07:00
Kir Kolyshkin d08bc0c1b3 runc run: warn on non-empty cgroup
Currently runc allows multiple containers to share the same cgroup (for
example, by having the same cgroupPath in config.json). While such
shared configuration might be OK, there are some issues:

 - When each container has its own resource limits, the order of
   containers start determines whose limits will be effectively applied.

 - When one of containers is paused, all others are paused, too.

 - When a container is paused, any attempt to do runc create/run/exec
   end up with runc init stuck inside a frozen cgroup.

 - When a systemd cgroup manager is used, this becomes even worse -- such
   as, stop (or even failed start) of any container results in
   "stopTransientUnit" command being sent to systemd, and so (depending on
   unit properties) other containers can receive SIGTERM, be killed after a
   timeout etc.

Any of the above may lead to various hard-to-debug situations in production
(runc init stuck, cgroup removal error, wrong resource limits, init not
reaping zombies etc.).

One obvious solution is to refuse a non-empty cgroup when starting a new
container. This would be a breaking change though, so let's make it in
steps, with the first step is issue a warning and a deprecated notice
about a non-empty cgroup.

Later (in runc 1.2) we will replace this warning with an error.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-11-03 20:36:27 -07:00
Kir Kolyshkin 972aea3af0 libct/configs/validate: allow / in sysctl names
Runtime spec says:

> sysctl (object, OPTIONAL) allows kernel parameters to be modified at
> runtime for the container. For more information, see the sysctl(8)
> man page.

and sysctl(8) says:

> variable
>    The name of a key to read from. An example is
>    kernel.ostype. The '/' separator is also accepted in place of a '.'.

Apparently, runc config validator do not support sysctls with / as a
separator. Fortunately this is a one-line fix.

Add some more test data where / is used as a separator.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-10-29 09:45:55 -07:00