Commit Graph

2123 Commits

Author SHA1 Message Date
Akihiro Suda 3a041e9654 Merge pull request #3081 from kolyshkin/carry-3065
Make cgroup freezer only care about current control group (carry #3065)
2021-07-12 13:09:40 +09:00
Qiang Huang 9493bb8268 Merge pull request #3041 from kolyshkin/rtd-cleanups
libcontainer/intelrdt: cleanups
2021-07-10 11:54:43 +08:00
Kir Kolyshkin 497e4032bd Merge pull request #3058 from kinvolk/rata/nsexec-close-bug
libcontainer: Don't close already closed fds and bail on close(2) failures
2021-07-09 11:35:36 -07:00
Odin Ugedal 3e5c199708 libct/cg/sd: Add freezer tests
This test the issues fixed by the two preceding commits.

Co-Authored-By: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Odin Ugedal <odin@uged.al>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-07-08 19:32:39 -07:00
Odin Ugedal 294c4866ea libct/cg/fs/freezer.GetState: report current cgroup state
If a control group is frozen, all its descendants will report FROZEN
in freezer.state cgroup file.

OTOH cgroup v2 cgroup.freeze is not reporting the cgroup as frozen
unless it is frozen directly (i.e. not via an ancestor).

Fix the discrepancy between v1 and v2 drivers behavior by
looking into freezer.self_freezing cgroup file, which, according
to kernel documentation, will show 1 iff the cgroup was frozen directly.

Co-authored-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Odin Ugedal <odin@uged.al>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-07-08 19:32:08 -07:00
Aleksa Sarai 262f294a2a merge branch 'pr-3062'
Kir Kolyshkin (3):
  libct/user: use []byte more, avoid allocations
  libct/user: ParseGroupFilter: use TrimSpace
  libct/user: fix parsing long /etc/group lines

LGTMs: AkihiroSuda cyphar
Closes #3062
2021-07-08 17:10:26 +10:00
Kir Kolyshkin 24d5daf54d libct/user: fix parsing long /etc/group lines
Lines in /etc/group longer than 64 characters breaks the current
implementation of group parser. This is caused by bufio.Scanner
buffer limit.

Fix by re-using the fix for a similar problem in golang os/user,
namely https://go-review.googlesource.com/c/go/+/283601.

Add some tests.

Co-authored-by: Andrey Bokhanko <andreybokhanko@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-07-02 13:19:42 -07:00
Kir Kolyshkin 226dfab0bc libct/user: ParseGroupFilter: use TrimSpace
Same as in other places (other parsers here, as well as golang os/user
parser and glibc parser all tolerate extra space at BOL and EOL).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-07-02 12:25:51 -07:00
Kir Kolyshkin 120e3a77d8 libct/user: use []byte more, avoid allocations
Every []byte to string conversion results in a new allocation.
Avoid some by using []byte more.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-07-02 12:25:45 -07:00
Rodrigo Campos 83776dd8b3 libcontainer: Bail on close(2) failures
Don't ignore close(2) return code, rather bail if there is any
unexpected failures. By checking the close return code we make sure we
don't introduce the same bug (closing an already closed fd) I've fixed
in the previous patch.

As a side note, we are not handling in this patch when close(2) returns
EINTR and the go runtime, since go 1.14, sends SIGURG to preempt
goroutines. This should not happen here though, as nsenter is guaranteed
to be executed before the go runtime starts.

Signed-off-by: Rodrigo Campos <rodrigo@kinvolk.io>
2021-07-02 16:43:25 +02:00
Rodrigo Campos 7d479e6beb libcontainer: Don't close fds already closed
This was closed in the child[1], before calling clone_parent (so runc
INIT will have this fd closed too), there is no point closing it again.

This was not causing issues because we ignore the return code of
close(2) and no one was opening a new fd between both calls to close.
However, with the new patches that I'm working on (PR #2576), this
problem is no longer inocuos: we do open a new fd in that PR, sometimes
that fd is allocated between the two close(2) calls and, as the lowest
fd is allocated to the new fd, sometimes the second close ends up
incorrectly closing this new fd.

Before it was not a problem in practice, but it was incorrect
nevertheless.

This seems to be long standing bug, present since at least 2018
(a54316bae), when SYNC_GRANDCHILD was introduced.

[1]: https://github.com/opencontainers/runc/blob/5547b5774f71f75a088e7432fa961778750a0fbd/libcontainer/nsenter/nsexec.c#L888

Co-authored-by: Alban Crequy <alban@kinvolk.io>
Signed-off-by: Rodrigo Campos <rodrigo@kinvolk.io>
2021-07-02 15:55:11 +02:00
Maksim An e39ad65059 retry unix.EINTR for container init process
When running a script from an azure file share interrupted syscall
occurs quite frequently, to remedy this add retries around execve
syscall, when EINTR is returned.

Signed-off-by: Maksim An <maksiman@microsoft.com>
2021-06-30 22:22:31 -07:00
Akihiro Suda 5547b5774f Merge pull request #3033 from kolyshkin/rm-own-errors
libcontainer: rm own error system
2021-07-01 13:47:27 +09:00
Kailun Qin c508a7bc0a libct/rootfs: consolidate utils imports
Signed-off-by: Kailun Qin <kailun.qin@intel.com>
2021-06-30 06:49:38 -04:00
Kir Kolyshkin 0229a77a80 libcontainer/intelrdt: privatize some ids
These are not used anywhere outside of the package
(I have also checked the only external user of the package
(github.com/google/cadvisor).

No changes other than changing the case. The following
identifiers are now private:

 * IntelRdtTasks
 * NewLastCmdError
 * NewStats

Brought to you by gorename.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin 8f8dfc498a libcontainer/intelrdt: move NewLastCmdError down
... the stack, so every caller will automatically benefit from it.

The only change that it causes is the user in
libcontainer/process_linux.go will get a better error message.

[v2: typo fix]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin 00d1562967 libct/intelrdt: simplify NewLastCmdError
For errors that only have a string and an underlying error, using
fmt.Errorf with %w to wrap an error is sufficient.

In this particular case, the code is simplified, and now we have
unwrappable errors as a bonus (same could be achieved by adding
(*LastCmdError).Unwrap() method, but that's adding more code).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin e0ce428bce libct/intelrdt: remove NotFoundError type
Initially, this was copied over from libcontainer/cgroups, where it made
sense as for cgroup v1 we have multiple controllers and mount points.

Here, we only have a single mount, so there's no need for the whole
type.

Replace all that with a simple error (which is currently internal since
the only user is our own test case).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin feff2c451e libct/intelrdt: fix potential nil dereference
In case getIntelRdtData() returns an error, d is set to nil.

In case the error returned is of NotFoundError type (which happens
if resctlr mount is not found in /proc/self/mountinfo), the function
proceeds to call d.join(), resulting in a nil deref and a panic.

In practice, this never happens in runc because of the checks in
intelrdt() function in libcontainer/configs/validate, which raises
an error in case any of the parameters are set in config but
the IntelRTD itself is not available (that includes checking
that the mount point is there).

Nevertheless, the code is wrong, and can result in nil dereference
if some external users uses Apply on a system without resctrl mount.

Fix this by removing the exclusion.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin 82498e3d77 libct/specconf: remove unneeded checks
In cases we have something like

	if y != "" {
		x = y
	}

where both x and y are strings, and x was not set before,
it makes no sense to have a condition, as such code is
equivalent to mere

	x = y

Simplify such cases by removing "if".

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-28 12:45:28 -07:00
Kir Kolyshkin 70fdc0573d Revert "checkpoint: resolve symlink for external bind mount"
This reverts commit da22625f69
(PR 2902).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-24 20:52:43 -07:00
Mrunal Patel 1079288bef Merge pull request #2902 from liusdu/checkpoint
checkpoint: resolve symlink for external bind mount
2021-06-24 22:52:02 -04:00
Mrunal Patel 245fe2b678 Merge pull request #3029 from liusdu/work
checkpoint: set default work-dir to image-path
2021-06-24 22:44:48 -04:00
Kir Kolyshkin e618c02d85 libct/stacktrace: remove
This removes the libcontainer/stacktrace package, which, as of previous
commit, is no longer used.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-24 10:21:51 -07:00
Kir Kolyshkin e918d02139 libcontainer: rm own error system
This removes libcontainer's own error wrapping system, consisting of a
few types and functions, aimed at typization, wrapping and unwrapping
of errors, as well as saving error stack traces.

Since Go 1.13 now provides its own error wrapping mechanism and a few
related functions, it makes sense to switch to it.

While doing that, improve some error messages so that they start
with "error", "unable to", or "can't".

A few things that are worth mentioning:

1. We lose stack traces (which were never shown anyway).

2. Users of libcontainer that relied on particular errors (like
   ContainerNotExists) need to switch to using errors.Is with
   the new errors defined in error.go.

3. encoding/json is unable to unmarshal the built-in error type,
   so we have to introduce initError and wrap the errors into it
   (basically passing the error as a string). This is the same
   as it was before, just a tad simpler (actually the initError
   is a type that got removed in commit afa844311; also suddenly
   ierr variable name makes sense now).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-24 10:21:04 -07:00
Kir Kolyshkin 60c647a783 libct/error: rm ConsoleExists
It is not used since commit 244c9fc426.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-24 08:24:58 -07:00
Kir Kolyshkin a7cfb23b88 *: stop using pkg/errors
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin b60e2edf75 libct/cg: stop using pkg/errors
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin a6cc36a836 libct/cg/ebpf: stop using pkg/errors
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin f137aaa2c8 libct/cg/devices: stop using pkg/errors
Use Go native errors wrapping.

Introduce wrapErr helper to minimise the patch size.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin 56e478046a *: ignore errorlint warnings about unix.* errors
Errors from unix.* are always bare and thus can be used directly.

Add //nolint:errorlint annotation to ignore errors such as these:

libcontainer/system/xattrs_linux.go:18:7: comparing with == will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint)
	case errno == unix.ERANGE:
	     ^
libcontainer/container_linux.go:1259:9: comparing with != will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint)
					if e != unix.EINVAL {
					   ^
libcontainer/rootfs_linux.go:919:7: comparing with != will fail on wrapped errors. Use errors.Is to check for a specific error (errorlint)
			if err != unix.EINVAL && err != unix.EPERM {
			   ^
libcontainer/rootfs_linux.go:1002:4: switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors (errorlint)
			switch err {
			^

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin f6a0899b7f *: use errors.As and errors.Is
Do this for all errors except one from unix.*.

This fixes a bunch of errorlint warnings, like these

libcontainer/generic_error.go:25:15: type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors (errorlint)
	if le, ok := err.(Error); ok {
	             ^
libcontainer/factory_linux_test.go:145:14: type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors (errorlint)
	lerr, ok := err.(Error)
	            ^
libcontainer/state_linux_test.go:28:11: type assertion on error will fail on wrapped errors. Use errors.As to check for specific errors (errorlint)
	_, ok := err.(*stateTransitionError)
	         ^
libcontainer/seccomp/patchbpf/enosys_linux.go:88:4: switch on an error will fail on wrapped errors. Use errors.Is to check for specific errors (errorlint)
			switch err {
			^

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin c6fed264da libct/keys: stop using pkg/errors
Use fmt.Errorf with %w instead.

Convert the users to the new wrapping.

This fixes an errorlint warning.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin adbac31d88 libct: fix errorlint warning about strconv.NumError
This one is tough as errorlint insists on using errors.Is, and the
latter is known to not work for Go 1.13 which we still support.

So, add a nolint annotation to suppress the warning, and a TODO to
address it later.

For intelrdt, we can do the same, but it is easier to reuse the very
same function from fscommon (note we can't use fscommon for other stuff
as it expects cgroupfs).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin 7be93a66b9 *: fmt.Errorf: use %w when appropriate
This should result in no change when the error is printed, but make the
errors returned unwrappable, meaning errors.As and errors.Is will work.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin d8ba4128b2 libct/rootfs: improve some errors
Errors from os.Open, os.Symlink etc do not need to be wrapped, as they
are already wrapped into os.PathError.

Error from unix are bare errnos and need to be wrapped. Same
os.PathError is a good candidate.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:47 -07:00
Kir Kolyshkin 36aefad45d libct: wrap unix.Mount/Unmount errors
Errors returned by unix are bare. In some cases it's impossible to find
out what went wrong because there's is not enough context.

Add a mountError type (mostly copy-pasted from github.com/moby/sys/mount),
and mount/unmount helpers. Use these where appropriate, and convert error
checks to use errors.Is.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 16:09:37 -07:00
Kir Kolyshkin 825335b2b7 libct/cg/fs2: fix/unify parsing errors
This builds on top of recently introduced fscommon.ParseError.

Errors returned from parsers (mostly ones used by GetStats()) are all
different, and many are incomplete. For example, in many cases errors
from strconv.ParseUint are returned as is, meaning there is no context
telling which file we were reading. Similarly, errors from
fscommon.ParseKeyValue should be wrapped to add more context.
Same is true for scanner.Err().

OTOH, errors from fscommon.GetCgroup* do have enough context and there
is no need to wrap them.

Fix all the above.

While at it, add missing scanner.Err() checks.

[v2: use parseError, not ParseError]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 12:00:54 -07:00
Kir Kolyshkin 5a186d390f libct/cg/fs: fix/unify parsing errors
This builds on top of recently introduced fscommon.ParseError.

Errors returned from parsers (mostly ones used by GetStats()) are all
different, and many are incomplete. For example, in many cases errors
from strconv.ParseUint are returned as is, meaning there is no context
telling which file we were reading. Similarly, errors from
fscommon.ParseKeyValue should be wrapped to add more context.
Same is true for scanner.Err().

One special case that repeats a few times is "malformed line: xxx".
Add and use a helper for that to simplify things.

OTOH, errors from fscommon.GetCgroup* do have enough context and there
is no need to wrap them.

Fix all the above.

While at it, add a missing scanner.Err() check.

[v2: use parseError not ParseError]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:59:54 -07:00
Kir Kolyshkin f813174d5e libct/cg/fscommon: introduce and use ParseError
1. Introduce ParseError type as a way to unify error messages related to
   file parsing. Use it from GetCgroup* functions.

2. Do not discard the error from strconv.Parse{Int,Uint} -- it contains
   the value being parsed, and the details about the error.

2. As the error above already contains the value, drop it from format.

[v2: use path.Join in Error]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:52:26 -07:00
Kir Kolyshkin adcd3b4451 libct/cg/fs[2]: simplify getting pid stats
1. Do not wrap errors returned from fscommon.GetCgroupParamUint -- those
   errors already have enough context.

2. Instead of parsing "max" ourselves, use GetCgroupParamUint which does
   it, and then convert MaxUint64 to 0 (we do it historically since
   commit 087b953dc5, and while using MaxUint64 as is seems fine,
   there may be some existing users who rely on the old behavior).

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:44:31 -07:00
Kir Kolyshkin 4e33094277 libct/cg/fs/stats_util_test: fix errors
1. No \n needed in t.Errorf/t.Fatalf.

2. Some cosmetic changes.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:44:12 -07:00
Kir Kolyshkin 563225d55f libct/StartInitialization: fix errors
Errors from strconv.Atoi are already descriptive enough, and contain the
value being converted, so our error messages do not need to contain it.

While at it, use %w to wrap errors.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:43:44 -07:00
Kir Kolyshkin 3fee59f9da libct/cg/fs/*_test: simplify errors
The error from fscommon.GetCgroup* already contains the file name and so
on, so there's no need to wrap it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:43:24 -07:00
Kir Kolyshkin fdf4e90e89 libct/cg/fscommon.ParseKeyValue: no need to wrap err
The error returned from strconv.ParseUint is already pretty descriptive,
something like:

	strconv.ParseUint: parsing "000d": invalid syntax

So, there is no need to add more context to it.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:42:59 -07:00
Kir Kolyshkin 627a06ad92 Replace fmt.Errorf w/o %-style to errors.New
Using fmt.Errorf for errors that do not have %-style formatting
directives is an overkill. Switch to errors.New.

Found by

	git grep fmt.Errorf | grep -v ^vendor | grep -v '%'

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:42:07 -07:00
Kir Kolyshkin 242b3283fd libct/cg/fscommon: rm unused var
It is not used since commit 494f900e91

Fixes: 494f900e91
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:42:00 -07:00
Kir Kolyshkin 92e8d9b91a libct/intelrdt: error message nits
An errror from ioutil.WriteFile already contains file name, so there is
no need to duplicate that information.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-22 11:41:41 -07:00
Liu Hua 85aabe233e C/R: let criu use its default if --work-path is not set
Now runc puts dump/restore logs in c.root defaultly, which will be deleted
when container exits. So if checkpinting/restoring failed, we can not get
these logs and analyze why.

This patch lets criu use its default if --work-path is not set:
 - Use WorkDirectory found in criu's configfile.
 - Use ImageDirectory.

Signed-off-by: Liu Hua <weldonliu@tencent.com>
2021-06-16 20:47:25 +08:00
Kir Kolyshkin 1036f3f995 libct/cg/fs2: set per-device io weight if available
Per-device weight is supported since kernel v5.4 (kernel commit
795fe54c2a8), so let's set those if supplied.

[v2: implement a more relaxed check in bfqDeviceWeightSupported]

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
2021-06-16 04:51:19 -07:00