From ec5896c6deaa050bfc185cfc9b464f7c8b859fe2 Mon Sep 17 00:00:00 2001 From: zhongjiawei Date: Thu, 22 Sep 2022 15:58:04 +0800 Subject: [PATCH] containerd: bugfix and add CGO serurity build option --- containerd.spec | 8 +- ...containerd-compile-option-compliance.patch | 43 + patch/0069-containerd-add-check-in-spec.patch | 27 + ...container-init-process-if-runc-start.patch | 105 ++ ...ontainerd-shim-residual-when-kill-co.patch | 45 + ...tainerd-fix-deadlock-on-commit-error.patch | 60 + ...containerd-backport-upstream-patches.patch | 1212 +++++++++++++++++ ...-exec-event-missing-due-to-pid-reuse.patch | 71 + ...t-when-pause-contaienr-and-kill-shim.patch | 36 + ...inerd-add-CGO-security-build-options.patch | 29 + ...tart-container-failed-with-id-exists.patch | 34 + patch/0078-containerd-drop-opt-package.patch | 25 + ...erd-bump-containerd-ttrpc-699c4e40d1.patch | 149 ++ ...rd-fix-race-access-for-mobySubcribed.patch | 47 + ...containerd-improve-log-for-debugging.patch | 137 ++ ...rd-reduce-permissions-for-bundle-di.patch} | 21 +- ...d-fix-publish-command-wait-block-for.patch | 25 + ...t-manifest-provided-URLs-differently.patch | 65 + ...-Use-chmod-path-for-checking-symlink.patch | 30 + ...086-containerd-Add-lock-for-ListPids.patch | 31 + ...rd-Use-fs.RootPath-when-mounting-vo.patch} | 6 +- ...idate-document-type-before-unmarshal.patch | 117 ++ ...9-schema1-reject-ambiguous-documents.patch | 43 + ...id-lock-after-set-process-exited-to-.patch | 37 + ...nerd-add-CGO-sercurity-build-options.patch | 38 + ...Limit-the-response-size-of-ExecSync.patch} | 0 series.conf | 29 +- 27 files changed, 2452 insertions(+), 18 deletions(-) create mode 100644 patch/0068-containerd-compile-option-compliance.patch create mode 100644 patch/0069-containerd-add-check-in-spec.patch create mode 100644 patch/0070-containerd-kill-container-init-process-if-runc-start.patch create mode 100644 patch/0071-containerd-fix-containerd-shim-residual-when-kill-co.patch create mode 100644 patch/0072-containerd-fix-deadlock-on-commit-error.patch create mode 100644 patch/0073-containerd-backport-upstream-patches.patch create mode 100644 patch/0074-containerd-fix-exec-event-missing-due-to-pid-reuse.patch create mode 100644 patch/0075-containerd-fix-dm-left-when-pause-contaienr-and-kill-shim.patch create mode 100644 patch/0076-containerd-add-CGO-security-build-options.patch create mode 100644 patch/0077-containerd-fix-start-container-failed-with-id-exists.patch create mode 100644 patch/0078-containerd-drop-opt-package.patch create mode 100644 patch/0079-containerd-bump-containerd-ttrpc-699c4e40d1.patch create mode 100644 patch/0080-containerd-fix-race-access-for-mobySubcribed.patch create mode 100644 patch/0081-containerd-improve-log-for-debugging.patch rename patch/{0068-containerd-reduce-permissions-for-bundle-dir-to-fix-.patch => 0082-containerd-reduce-permissions-for-bundle-di.patch} (88%) create mode 100644 patch/0083-containerd-fix-publish-command-wait-block-for.patch create mode 100644 patch/0084-containerd-treat-manifest-provided-URLs-differently.patch create mode 100644 patch/0085-containerd-Use-chmod-path-for-checking-symlink.patch create mode 100644 patch/0086-containerd-Add-lock-for-ListPids.patch rename patch/{0069-containerd-Use-fs.RootPath-when-mounting-vo.patch => 0087-containerd-Use-fs.RootPath-when-mounting-vo.patch} (87%) create mode 100644 patch/0088-images-validate-document-type-before-unmarshal.patch create mode 100644 patch/0089-schema1-reject-ambiguous-documents.patch create mode 100644 patch/0090-containerd-put-get-pid-lock-after-set-process-exited-to-.patch create mode 100644 patch/0091-containerd-add-CGO-sercurity-build-options.patch rename patch/{0070-containerd-Limit-the-response-size-of-ExecSync.patch => 0092-containerd-Limit-the-response-size-of-ExecSync.patch} (100%) diff --git a/containerd.spec b/containerd.spec index 07d5f03..0b11bf8 100644 --- a/containerd.spec +++ b/containerd.spec @@ -2,7 +2,7 @@ %global debug_package %{nil} Version: 1.2.0 Name: containerd -Release: 203 +Release: 204 Summary: An industry-standard container runtime License: ASL 2.0 URL: https://containerd.io @@ -41,6 +41,12 @@ install -p -m 755 bin/containerd-shim $RPM_BUILD_ROOT/%{_bindir}/containerd-shim %{_bindir}/containerd-shim %changelog +* Thu Sep 22 2022 zhongjiawei - 1.2.0-204 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC: bugfix fix and add CGO security build options + * Mon Jul 4 2022 zhongjiawei - 1.2.0-203 - Type:bugfix - ID:NA diff --git a/patch/0068-containerd-compile-option-compliance.patch b/patch/0068-containerd-compile-option-compliance.patch new file mode 100644 index 0000000..8cde5c7 --- /dev/null +++ b/patch/0068-containerd-compile-option-compliance.patch @@ -0,0 +1,43 @@ +From 821e1ae98bbbf8756d628a8bdb9ffd87701a2fae Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Tue, 26 Jan 2021 20:40:30 +0800 +Subject: [PATCH] containerd: compile option compliance + +reason:compile option compliance + +Change-Id: I779d0ae7ed1da3050b5d38631c8c44e090d2d55a +Signed-off-by: xiadanni +--- + Makefile | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/Makefile b/Makefile +index f69559b..dbc399e 100644 +--- a/Makefile ++++ b/Makefile +@@ -82,7 +82,7 @@ BEP_DIR=/tmp/containerd-build-bep + BEP_FLAGS=-tmpdir=/tmp/containerd-build-bep + + GO_LDFLAGS=-ldflags ' -buildid=IdByIsula -extldflags=-zrelro -extldflags=-znow $(BEP_FLAGS) -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) $(EXTRA_LDFLAGS)' +-SHIM_GO_LDFLAGS=-ldflags ' -buildid=IdByIsula $(BEP_FLAGS) -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -extldflags "-static"' ++SHIM_GO_LDFLAGS=-ldflags '-extldflags=-static' -ldflags '-buildid=IdByIsula $(BEP_FLAGS) -X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -linkmode=external -extldflags=-Wl,-z,relro,-z,now' + + #Replaces ":" (*nix), ";" (windows) with newline for easy parsing + GOPATHS=$(shell echo ${GOPATH} | tr ":" "\n" | tr ";" "\n") +@@ -175,7 +175,12 @@ bin/%: cmd/% FORCE + + bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 + @echo "$(WHALE) bin/containerd-shim" +- go build ${GO_BUILD_FLAGS} -o bin/containerd-shim ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim ++ CGO_ENABLED=1 \ ++ CGO_CFLAGS="-fstack-protector-strong -fPIE" \ ++ CGO_CPPFLAGS="-fstack-protector-strong -fPIE" \ ++ CGO_LDFLAGS_ALLOW='-Wl,-z,relro,-z,now' \ ++ CGO_LDFLAGS="-Wl,-z,relro,-z,now -Wl,-z,noexecstack" \ ++ go build -buildmode=pie ${GO_BUILD_FLAGS} -o bin/containerd-shim ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim + + bin/containerd-shim-runc-v1: cmd/containerd-shim-runc-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 + @echo "$(WHALE) bin/containerd-shim-runc-v1" +-- +1.8.3.1 + diff --git a/patch/0069-containerd-add-check-in-spec.patch b/patch/0069-containerd-add-check-in-spec.patch new file mode 100644 index 0000000..2e96fe0 --- /dev/null +++ b/patch/0069-containerd-add-check-in-spec.patch @@ -0,0 +1,27 @@ +From 27be5a04fc8b28e14ff296f5b9356ace8feb39ce Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Thu, 18 Feb 2021 20:28:52 +0800 +Subject: [PATCH] containerd: add check in spec + +Change-Id: I8ddf63ec1c4da479e90838678136237b5822d463 +Signed-off-by: xiadanni +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 96c2370..511b6f2 100644 +--- a/Makefile ++++ b/Makefile +@@ -151,7 +151,7 @@ build: ## build the go packages + + test: ## run tests, except integration tests and tests that require root + @echo "$(WHALE) $@" +- @go test ${TESTFLAGS} $(filter-out ${INTEGRATION_PACKAGE},${PACKAGES}) ++ @go test ${TESTFLAGS} ./gc + + root-test: ## run tests, except integration tests + @echo "$(WHALE) $@" +-- +1.8.3.1 + diff --git a/patch/0070-containerd-kill-container-init-process-if-runc-start.patch b/patch/0070-containerd-kill-container-init-process-if-runc-start.patch new file mode 100644 index 0000000..5418555 --- /dev/null +++ b/patch/0070-containerd-kill-container-init-process-if-runc-start.patch @@ -0,0 +1,105 @@ +From 52d42e0b850cde3600028b00e19f5325a61ddad3 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Mon, 1 Feb 2021 19:36:53 +0800 +Subject: [PATCH] containerd: kill container init process if runc start returns + error + +Signed-off-by: xiadanni +--- + runtime/v1/linux/proc/init.go | 4 +++ + utils/utils.go | 61 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 65 insertions(+) + create mode 100644 utils/utils.go + +diff --git a/runtime/v1/linux/proc/init.go b/runtime/v1/linux/proc/init.go +index de76682..669c108 100644 +--- a/runtime/v1/linux/proc/init.go ++++ b/runtime/v1/linux/proc/init.go +@@ -35,6 +35,7 @@ import ( + "github.com/containerd/containerd/log" + "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/runtime/proc" ++ "github.com/containerd/containerd/utils" + "github.com/containerd/fifo" + runc "github.com/containerd/go-runc" + google_protobuf "github.com/gogo/protobuf/types" +@@ -277,6 +278,9 @@ func (p *Init) Status(ctx context.Context) (string, error) { + + func (p *Init) start(context context.Context) error { + err := p.runtime.Start(context, p.id) ++ if err != nil { ++ utils.KillInitProcess(p.id, p.pid) ++ } + return p.runtimeError(err, "OCI runtime start failed") + } + +diff --git a/utils/utils.go b/utils/utils.go +new file mode 100644 +index 0000000..c57c6ca +--- /dev/null ++++ b/utils/utils.go +@@ -0,0 +1,61 @@ ++/* ++Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. ++Use of this source code is governed by Apache-2.0 ++license that can be found in the LICENSE file. ++Description: common functions ++Author: Danni Xia ++Create: 2021-01-30 ++*/ ++ ++package utils ++ ++import ( ++ "encoding/json" ++ "io/ioutil" ++ "path/filepath" ++ "strconv" ++ "strings" ++ "syscall" ++ ++ "github.com/sirupsen/logrus" ++) ++ ++type baseState struct { ++ InitProcessStartTime string `json:"init_process_start"` ++} ++ ++func KillInitProcess(cid string, pid int) { ++ if IsInitProcess(cid, pid) { ++ syscall.Kill(pid, syscall.SIGKILL) ++ } ++} ++ ++func IsInitProcess(cid string, pid int) bool { ++ stateBytes, err1 := ioutil.ReadFile(filepath.Join("/var/run/docker/runtime-runc/moby", cid, "state.json")) ++ statBytes, err2 := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) ++ if err1 != nil || err2 != nil { ++ return true ++ } ++ ++ s := strings.Split(string(statBytes), ")") ++ if len(s) < 1 { ++ return true ++ } ++ ++ statFields := strings.Split(strings.TrimSpace(s[len(s)-1]), " ") ++ if len(statFields) < 20 { ++ return true ++ } ++ ++ var baseState baseState ++ if err := json.Unmarshal(stateBytes, &baseState); err != nil { ++ return true ++ } ++ ++ if baseState.InitProcessStartTime == statFields[19] { ++ return true ++ } ++ ++ logrus.Warnf("process(pid:%d, start time:%s) is not container %s init process", pid, statFields[19], cid) ++ return false ++} +-- +1.8.3.1 + diff --git a/patch/0071-containerd-fix-containerd-shim-residual-when-kill-co.patch b/patch/0071-containerd-fix-containerd-shim-residual-when-kill-co.patch new file mode 100644 index 0000000..c6c4b6c --- /dev/null +++ b/patch/0071-containerd-fix-containerd-shim-residual-when-kill-co.patch @@ -0,0 +1,45 @@ +From 5d72fe2c0d6774e94cad6feacec87db703104fe7 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Fri, 19 Feb 2021 16:37:48 +0800 +Subject: [PATCH] containerd: fix containerd-shim residual when kill containerd + during starting container + +after shim process started, containerd will write shim socket address +to address file, but if containerd is killed before write file, new +containerd process could not get shim socket address, and will not +kill it even if that shim could not work. +so we write address file ahead of starting shim process. + +Signed-off-by: xiadanni +--- + runtime/v1/shim/client/client.go | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/runtime/v1/shim/client/client.go b/runtime/v1/shim/client/client.go +index 9e63af4..bc9ac92 100644 +--- a/runtime/v1/shim/client/client.go ++++ b/runtime/v1/shim/client/client.go +@@ -92,6 +92,10 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa + go io.Copy(os.Stderr, stderrLog) + } + ++ if err := writeFile(filepath.Join(config.Path, "address"), address); err != nil { ++ return nil, nil, err ++ } ++ + cmd, err := newCommand(binary, daemonAddress, debug, config, f, stdoutLog, stderrLog) + if err != nil { + return nil, nil, err +@@ -122,9 +126,6 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa + "debug": debug, + }).Infof("shim %s started", binary) + +- if err := writeFile(filepath.Join(config.Path, "address"), address); err != nil { +- return nil, nil, err +- } + if err := writeFile(filepath.Join(config.Path, "shim.pid"), strconv.Itoa(cmd.Process.Pid)); err != nil { + return nil, nil, err + } +-- +1.8.3.1 + diff --git a/patch/0072-containerd-fix-deadlock-on-commit-error.patch b/patch/0072-containerd-fix-deadlock-on-commit-error.patch new file mode 100644 index 0000000..4dbb496 --- /dev/null +++ b/patch/0072-containerd-fix-deadlock-on-commit-error.patch @@ -0,0 +1,60 @@ +From 39183d7937d408afceb9456972ad3e42beb336c6 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Sat, 27 Feb 2021 11:19:22 +0800 +Subject: [PATCH] containerd:fix deadlock on commit error + +upstream:https://github.com/containerd/containerd/commit/5b9bd993a87008e06a34258f0672a78564adab13 +Signed-off-by: xiadanni +--- + content/local/writer.go | 5 +++-- + diff/walking/differ.go | 5 +++-- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/content/local/writer.go b/content/local/writer.go +index 223b145..3a94744 100644 +--- a/content/local/writer.go ++++ b/content/local/writer.go +@@ -74,6 +74,9 @@ func (w *writer) Write(p []byte) (n int, err error) { + } + + func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { ++ // Ensure even on error the writer is fully closed ++ defer unlock(w.ref) ++ + var base content.Info + for _, opt := range opts { + if err := opt(&base); err != nil { +@@ -81,8 +84,6 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, + } + } + +- // Ensure even on error the writer is fully closed +- defer unlock(w.ref) + fp := w.fp + w.fp = nil + +diff --git a/diff/walking/differ.go b/diff/walking/differ.go +index a45a563..1c82860 100644 +--- a/diff/walking/differ.go ++++ b/diff/walking/differ.go +@@ -106,14 +106,15 @@ func (s *walkingDiff) Compare(ctx context.Context, lower, upper []mount.Mount, o + } + }() + if !newReference { +- if err := cw.Truncate(0); err != nil { ++ if err = cw.Truncate(0); err != nil { + return err + } + } + + if isCompressed { + dgstr := digest.SHA256.Digester() +- compressed, err := compression.CompressStream(cw, compression.Gzip) ++ var compressed io.WriteCloser ++ compressed, err = compression.CompressStream(cw, compression.Gzip) + if err != nil { + return errors.Wrap(err, "failed to get compressed stream") + } +-- +1.8.3.1 + diff --git a/patch/0073-containerd-backport-upstream-patches.patch b/patch/0073-containerd-backport-upstream-patches.patch new file mode 100644 index 0000000..9bc3a8d --- /dev/null +++ b/patch/0073-containerd-backport-upstream-patches.patch @@ -0,0 +1,1212 @@ +From 470a207ed468b5473d7833987791f01b467141a3 Mon Sep 17 00:00:00 2001 +From: jingrui +Date: Fri, 5 Feb 2021 15:10:27 +0800 +Subject: [PATCH] containerd: backport upstream patches + +2019-11-27 15:29:44 -0800 b97098762 Fix container pid. Lantao Liu lantaol@google.com +2019-06-21 15:28:16 -0400 f71f6d39b Robust pid locking for shim processes Michael Crosby crosbymichael.. +2019-06-20 16:13:51 -0400 42aba6e0f Add timeout for I/O waitgroups Michael Crosby crosbymichael.. +2019-02-01 02:08:49 -0800 5730c5003 Add a separate lock for pid. Lantao Liu lantaol@google.com +2019-01-31 18:59:29 -0800 b9b7ef32b Revert "use state machine management for exec.Pid()" Lantao Liu lantaol@google.com +2019-01-22 16:19:09 -0800 ab2cf0136 Use context.Background for `O_NONBLOCK` `OpenFifo`. Lantao Liu lantaol@google.com +2018-11-23 17:46:32 +0800 c42c8952b use state machine management for exec.Pid() Lifubang lifubang@acmcoder.com +2018-11-09 11:12:55 -0500 4c72befe0 Fix process locking and state management Michael Crosby crosbymichael.. + +Conflict:NA +Reference:https://github.com/containerd/containerd/pull/3755 + +Change-Id: Ic7f768e72a38383c1b89680333c9ee234ea217aa +Signed-off-by: jingrui +--- + runtime/proc/proc.go | 5 - + runtime/v1/linux/proc/exec.go | 77 +++++++++--- + runtime/v1/linux/proc/exec_state.go | 59 +++------ + runtime/v1/linux/proc/init.go | 155 +++++++++++++++++------ + runtime/v1/linux/proc/init_state.go | 182 +++++----------------------- + runtime/v1/linux/proc/io.go | 2 +- + runtime/v1/linux/proc/utils.go | 12 ++ + runtime/v2/runc/service_linux.go | 2 +- + runtime/v2/shim_unix.go | 2 +- + 9 files changed, 235 insertions(+), 261 deletions(-) + +diff --git a/runtime/proc/proc.go b/runtime/proc/proc.go +index 02bc9bda8..91ca59bb1 100644 +--- a/runtime/proc/proc.go ++++ b/runtime/proc/proc.go +@@ -40,7 +40,6 @@ func (s Stdio) IsNull() bool { + + // Process on a system + type Process interface { +- State + // ID returns the id for the process + ID() string + // Pid returns the pid for the process +@@ -57,10 +56,6 @@ type Process interface { + Status(context.Context) (string, error) + // Wait blocks until the process has exited + Wait() +-} +- +-// State of a process +-type State interface { + // Resize resizes the process console + Resize(ws console.WinSize) error + // Start execution of the process +diff --git a/runtime/v1/linux/proc/exec.go b/runtime/v1/linux/proc/exec.go +index 08c581fbf..ea40cb5b8 100644 +--- a/runtime/v1/linux/proc/exec.go ++++ b/runtime/v1/linux/proc/exec.go +@@ -31,6 +31,7 @@ import ( + "golang.org/x/sys/unix" + + "github.com/containerd/console" ++ "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/runtime/proc" + "github.com/containerd/fifo" + runc "github.com/containerd/go-runc" +@@ -41,7 +42,7 @@ import ( + type execProcess struct { + wg sync.WaitGroup + +- proc.State ++ execState execState + + mu sync.Mutex + id string +@@ -49,7 +50,7 @@ type execProcess struct { + io runc.IO + status int + exited time.Time +- pid int ++ pid safePid + closers []io.Closer + stdin io.Closer + stdio proc.Stdio +@@ -69,9 +70,7 @@ func (e *execProcess) ID() string { + } + + func (e *execProcess) Pid() int { +- e.mu.Lock() +- defer e.mu.Unlock() +- return e.pid ++ return e.pid.get() + } + + func (e *execProcess) ExitStatus() int { +@@ -86,6 +85,13 @@ func (e *execProcess) ExitedAt() time.Time { + return e.exited + } + ++func (e *execProcess) SetExited(status int) { ++ e.mu.Lock() ++ defer e.mu.Unlock() ++ ++ e.execState.SetExited(status) ++} ++ + func (e *execProcess) setExited(status int) { + e.status = status + e.exited = time.Now() +@@ -93,6 +99,13 @@ func (e *execProcess) setExited(status int) { + close(e.waitBlock) + } + ++func (e *execProcess) Delete(ctx context.Context) error { ++ e.mu.Lock() ++ defer e.mu.Unlock() ++ ++ return e.execState.Delete(ctx) ++} ++ + func (e *execProcess) delete(ctx context.Context) error { + waitTimeout(ctx, &e.wg, 2*time.Second) + if e.io != nil { +@@ -107,6 +120,13 @@ func (e *execProcess) delete(ctx context.Context) error { + return nil + } + ++func (e *execProcess) Resize(ws console.WinSize) error { ++ e.mu.Lock() ++ defer e.mu.Unlock() ++ ++ return e.execState.Resize(ws) ++} ++ + func (e *execProcess) resize(ws console.WinSize) error { + if e.console == nil { + return nil +@@ -114,9 +134,21 @@ func (e *execProcess) resize(ws console.WinSize) error { + return e.console.Resize(ws) + } + ++func (e *execProcess) Kill(ctx context.Context, sig uint32, _ bool) error { ++ e.mu.Lock() ++ defer e.mu.Unlock() ++ ++ return e.execState.Kill(ctx, sig, false) ++} ++ + func (e *execProcess) kill(ctx context.Context, sig uint32, _ bool) error { +- pid := e.pid +- if pid != 0 { ++ pid := e.pid.get() ++ switch { ++ case pid == 0: ++ return errors.Wrap(errdefs.ErrFailedPrecondition, "process not created") ++ case !e.exited.IsZero(): ++ return errors.Wrapf(errdefs.ErrNotFound, "process already finished") ++ default: + if err := unix.Kill(pid, syscall.Signal(sig)); err != nil { + return errors.Wrapf(checkKillError(err), "exec kill error") + } +@@ -132,7 +164,20 @@ func (e *execProcess) Stdio() proc.Stdio { + return e.stdio + } + ++func (e *execProcess) Start(ctx context.Context) error { ++ e.mu.Lock() ++ defer e.mu.Unlock() ++ ++ return e.execState.Start(ctx) ++} ++ + func (e *execProcess) start(ctx context.Context) (err error) { ++ // The reaper may receive exit signal right after ++ // the container is started, before the e.pid is updated. ++ // In that case, we want to block the signal handler to ++ // access e.pid until it is updated. ++ e.pid.Lock() ++ defer e.pid.Unlock() + var ( + socket *runc.Socket + pidfile = filepath.Join(e.path, fmt.Sprintf("%s.pid", e.id)) +@@ -164,7 +209,7 @@ func (e *execProcess) start(ctx context.Context) (err error) { + return e.parent.runtimeError(err, "OCI runtime exec failed") + } + if e.stdio.Stdin != "" { +- sc, err := fifo.OpenFifo(ctx, e.stdio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) ++ sc, err := fifo.OpenFifo(context.Background(), e.stdio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + if err != nil { + return errors.Wrapf(err, "failed to open stdin fifo %s", e.stdio.Stdin) + } +@@ -173,29 +218,26 @@ func (e *execProcess) start(ctx context.Context) (err error) { + } + var copyWaitGroup sync.WaitGroup + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) ++ defer cancel() + if socket != nil { + console, err := socket.ReceiveMaster() + if err != nil { +- cancel() + return errors.Wrap(err, "failed to retrieve console master") + } + if e.console, err = e.parent.Platform.CopyConsole(ctx, console, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, ©WaitGroup); err != nil { +- cancel() + return errors.Wrap(err, "failed to start console copy") + } + } else if !e.stdio.IsNull() { + if err := copyPipes(ctx, e.io, e.stdio.Stdin, e.stdio.Stdout, e.stdio.Stderr, &e.wg, ©WaitGroup); err != nil { +- cancel() + return errors.Wrap(err, "failed to start io pipe copy") + } + } + copyWaitGroup.Wait() + pid, err := runc.ReadPidFile(opts.PidFile) + if err != nil { +- cancel() + return errors.Wrap(err, "failed to retrieve OCI runtime exec pid") + } +- e.pid = pid ++ e.pid.pid = pid + return nil + } + +@@ -212,12 +254,15 @@ func (e *execProcess) Status(ctx context.Context) (string, error) { + } + e.mu.Lock() + defer e.mu.Unlock() +- // if we don't have a pid then the exec process has just been created +- if e.pid == 0 { ++ // if we don't have a pid(pid=0) then the exec process has just been created ++ if e.pid.get() == 0 { + return "created", nil + } ++ if e.pid.get() == -1 { ++ return "stopped", nil ++ } + // if we have a pid and it can be signaled, the process is running +- if err := unix.Kill(e.pid, 0); err == nil { ++ if err := unix.Kill(e.pid.get(), 0); err == nil { + return "running", nil + } + // else if we have a pid but it can nolonger be signaled, it has stopped +diff --git a/runtime/v1/linux/proc/exec_state.go b/runtime/v1/linux/proc/exec_state.go +index ac5467552..12489501b 100644 +--- a/runtime/v1/linux/proc/exec_state.go ++++ b/runtime/v1/linux/proc/exec_state.go +@@ -25,6 +25,14 @@ import ( + "github.com/pkg/errors" + ) + ++type execState interface { ++ Resize(console.WinSize) error ++ Start(context.Context) error ++ Delete(context.Context) error ++ Kill(context.Context, uint32, bool) error ++ SetExited(int) ++} ++ + type execCreatedState struct { + p *execProcess + } +@@ -32,11 +40,11 @@ type execCreatedState struct { + func (s *execCreatedState) transition(name string) error { + switch name { + case "running": +- s.p.State = &execRunningState{p: s.p} ++ s.p.execState = &execRunningState{p: s.p} + case "stopped": +- s.p.State = &execStoppedState{p: s.p} ++ s.p.execState = &execStoppedState{p: s.p} + case "deleted": +- s.p.State = &deletedState{} ++ s.p.execState = &deletedState{} + default: + return errors.Errorf("invalid state transition %q to %q", stateName(s), name) + } +@@ -44,15 +52,10 @@ func (s *execCreatedState) transition(name string) error { + } + + func (s *execCreatedState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *execCreatedState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + if err := s.p.start(ctx); err != nil { + return err + } +@@ -63,22 +66,15 @@ func (s *execCreatedState) Delete(ctx context.Context) error { + if err := s.p.delete(ctx); err != nil { + return err + } +- s.p.mu.Lock() +- defer s.p.mu.Unlock() ++ + return s.transition("deleted") + } + + func (s *execCreatedState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *execCreatedState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + + if err := s.transition("stopped"); err != nil { +@@ -93,7 +89,7 @@ type execRunningState struct { + func (s *execRunningState) transition(name string) error { + switch name { + case "stopped": +- s.p.State = &execStoppedState{p: s.p} ++ s.p.execState = &execStoppedState{p: s.p} + default: + return errors.Errorf("invalid state transition %q to %q", stateName(s), name) + } +@@ -101,37 +97,22 @@ func (s *execRunningState) transition(name string) error { + } + + func (s *execRunningState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *execRunningState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot start a running process") + } + + func (s *execRunningState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot delete a running process") + } + + func (s *execRunningState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *execRunningState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + + if err := s.transition("stopped"); err != nil { +@@ -146,7 +127,7 @@ type execStoppedState struct { + func (s *execStoppedState) transition(name string) error { + switch name { + case "deleted": +- s.p.State = &deletedState{} ++ s.p.execState = &deletedState{} + default: + return errors.Errorf("invalid state transition %q to %q", stateName(s), name) + } +@@ -154,16 +135,10 @@ func (s *execStoppedState) transition(name string) error { + } + + func (s *execStoppedState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resize a stopped container") + } + + func (s *execStoppedState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot start a stopped process") + } + +@@ -171,15 +146,11 @@ func (s *execStoppedState) Delete(ctx context.Context) error { + if err := s.p.delete(ctx); err != nil { + return err + } +- s.p.mu.Lock() +- defer s.p.mu.Unlock() ++ + return s.transition("deleted") + } + + func (s *execStoppedState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + +diff --git a/runtime/v1/linux/proc/init.go b/runtime/v1/linux/proc/init.go +index 669c1085d..108234904 100644 +--- a/runtime/v1/linux/proc/init.go ++++ b/runtime/v1/linux/proc/init.go +@@ -52,8 +52,8 @@ const DefaultRunvRoot = "/run/runv" + + // Init represents an initial process for a container + type Init struct { +- wg sync.WaitGroup +- initState ++ wg sync.WaitGroup ++ initState initState + + // mu is used to ensure that `Start()` and `Exited()` calls return in + // the right order when invoked in separate go routines. +@@ -65,12 +65,12 @@ type Init struct { + + WorkDir string + +- id string +- Bundle string +- console console.Console +- Platform proc.Platform +- io runc.IO +- runtime *runc.Runc ++ id string ++ Bundle string ++ console console.Console ++ Platform proc.Platform ++ io runc.IO ++ runtime *runc.Runc + status int + exited time.Time + pid int +@@ -138,6 +138,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { + err error + socket *runc.Socket + ) ++ + pidFile := filepath.Join(p.Bundle, InitPidFile) + + if legacy.IsLegacy(r.ID) { +@@ -195,7 +196,7 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { + return p.runtimeError(err, "OCI runtime create failed") + } + if r.Stdin != "" { +- sc, err := fifo.OpenFifo(ctx, r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) ++ sc, err := fifo.OpenFifo(context.Background(), r.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + if err != nil { + return errors.Wrapf(err, "failed to open stdin fifo %s", r.Stdin) + } +@@ -204,21 +205,19 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { + } + var copyWaitGroup sync.WaitGroup + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) ++ defer cancel() + if socket != nil { + console, err := socket.ReceiveMaster() + if err != nil { +- cancel() + return errors.Wrap(err, "failed to retrieve console master") + } + console, err = p.Platform.CopyConsole(ctx, console, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup) + if err != nil { +- cancel() + return errors.Wrap(err, "failed to start console copy") + } + p.console = console + } else if !hasNoIO(r) { + if err := copyPipes(ctx, p.io, r.Stdin, r.Stdout, r.Stderr, &p.wg, ©WaitGroup); err != nil { +- cancel() + return errors.Wrap(err, "failed to start io pipe copy") + } + } +@@ -226,7 +225,6 @@ func (p *Init) Create(ctx context.Context, r *CreateConfig) error { + copyWaitGroup.Wait() + pid, err := runc.ReadPidFile(pidFile) + if err != nil { +- cancel() + return errors.Wrap(err, "failed to retrieve OCI runtime container pid") + } + p.pid = pid +@@ -266,6 +264,7 @@ func (p *Init) ExitedAt() time.Time { + func (p *Init) Status(ctx context.Context) (string, error) { + p.mu.Lock() + defer p.mu.Unlock() ++ + c, err := p.runtime.State(ctx, p.id) + if err != nil { + if strings.Contains(err.Error(), "does not exist") { +@@ -276,14 +275,30 @@ func (p *Init) Status(ctx context.Context) (string, error) { + return c.Status, nil + } + +-func (p *Init) start(context context.Context) error { +- err := p.runtime.Start(context, p.id) ++// Start the init process ++func (p *Init) Start(ctx context.Context) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Start(ctx) ++} ++ ++func (p *Init) start(ctx context.Context) error { ++ err := p.runtime.Start(ctx, p.id) + if err != nil { + utils.KillInitProcess(p.id, p.pid) + } + return p.runtimeError(err, "OCI runtime start failed") + } + ++// SetExited of the init process with the next status ++func (p *Init) SetExited(status int) { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ p.initState.SetExited(status) ++} ++ + func (p *Init) setExited(status int) { + p.exited = time.Now() + p.status = status +@@ -291,9 +306,17 @@ func (p *Init) setExited(status int) { + close(p.waitBlock) + } + +-func (p *Init) delete(context context.Context) error { +- waitTimeout(context, &p.wg, 2*time.Second) +- err := p.runtime.Delete(context, p.id, nil) ++// Delete the init process ++func (p *Init) Delete(ctx context.Context) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Delete(ctx) ++} ++ ++func (p *Init) delete(ctx context.Context) error { ++ waitTimeout(ctx, &p.wg, 2*time.Second) ++ err := p.runtime.Delete(ctx, p.id, nil) + // ignore errors if a runtime has already deleted the process + // but we still hold metadata and pipes + // +@@ -312,15 +335,28 @@ func (p *Init) delete(context context.Context) error { + } + p.io.Close() + } +- if err2 := mount.UnmountAll(p.Rootfs, 0); err2 != nil { +- log.G(context).WithError(err2).Warn("failed to cleanup rootfs mount") +- if err == nil { +- err = errors.Wrap(err2, "failed rootfs umount") ++ if p.Rootfs != "" { ++ if err2 := mount.UnmountAll(p.Rootfs, 0); err2 != nil { ++ log.G(ctx).WithError(err2).Warn("failed to cleanup rootfs mount") ++ if err == nil { ++ err = errors.Wrap(err2, "failed rootfs umount") ++ } + } + } + return err + } + ++// Resize the init processes console ++func (p *Init) Resize(ws console.WinSize) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ if p.console == nil { ++ return nil ++ } ++ return p.console.Resize(ws) ++} ++ + func (p *Init) resize(ws console.WinSize) error { + if p.console == nil { + return nil +@@ -328,26 +364,43 @@ func (p *Init) resize(ws console.WinSize) error { + return p.console.Resize(ws) + } + +-func (p *Init) pause(context context.Context) error { +- err := p.runtime.Pause(context, p.id) +- return p.runtimeError(err, "OCI runtime pause failed") ++// Pause the init process and all its child processes ++func (p *Init) Pause(ctx context.Context) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Pause(ctx) ++} ++ ++// Resume the init process and all its child processes ++func (p *Init) Resume(ctx context.Context) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Resume(ctx) + } + +-func (p *Init) resume(context context.Context) error { +- err := p.runtime.Resume(context, p.id) +- return p.runtimeError(err, "OCI runtime resume failed") ++// Kill the init process ++func (p *Init) Kill(ctx context.Context, signal uint32, all bool) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Kill(ctx, signal, all) + } + +-func (p *Init) kill(context context.Context, signal uint32, all bool) error { +- err := p.runtime.Kill(context, p.id, int(signal), &runc.KillOpts{ ++func (p *Init) kill(ctx context.Context, signal uint32, all bool) error { ++ err := p.runtime.Kill(ctx, p.id, int(signal), &runc.KillOpts{ + All: all, + }) + return checkKillError(err) + } + + // KillAll processes belonging to the init process +-func (p *Init) KillAll(context context.Context) error { +- err := p.runtime.Kill(context, p.id, int(syscall.SIGKILL), &runc.KillOpts{ ++func (p *Init) KillAll(ctx context.Context) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ err := p.runtime.Kill(ctx, p.id, int(syscall.SIGKILL), &runc.KillOpts{ + All: true, + }) + return p.runtimeError(err, "OCI runtime killall failed") +@@ -363,8 +416,16 @@ func (p *Init) Runtime() *runc.Runc { + return p.runtime + } + ++// Exec returns a new child process ++func (p *Init) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Exec(ctx, path, r) ++} ++ + // exec returns a new exec'd process +-func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.Process, error) { ++func (p *Init) exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { + // process exec request + var spec specs.Process + if err := json.Unmarshal(r.Spec.Value, &spec); err != nil { +@@ -385,18 +446,26 @@ func (p *Init) exec(context context.Context, path string, r *ExecConfig) (proc.P + }, + waitBlock: make(chan struct{}), + } +- e.State = &execCreatedState{p: e} ++ e.execState = &execCreatedState{p: e} + return e, nil + } + +-func (p *Init) checkpoint(context context.Context, r *CheckpointConfig) error { ++// Checkpoint the init process ++func (p *Init) Checkpoint(ctx context.Context, r *CheckpointConfig) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Checkpoint(ctx, r) ++} ++ ++func (p *Init) checkpoint(ctx context.Context, r *CheckpointConfig) error { + var actions []runc.CheckpointAction + if !r.Exit { + actions = append(actions, runc.LeaveRunning) + } + work := filepath.Join(p.WorkDir, "criu-work") + defer os.RemoveAll(work) +- if err := p.runtime.Checkpoint(context, p.id, &runc.CheckpointOpts{ ++ if err := p.runtime.Checkpoint(ctx, p.id, &runc.CheckpointOpts{ + WorkDir: work, + ImagePath: r.Path, + AllowOpenTCP: r.AllowOpenTCP, +@@ -407,19 +476,27 @@ func (p *Init) checkpoint(context context.Context, r *CheckpointConfig) error { + }, actions...); err != nil { + dumpLog := filepath.Join(p.Bundle, "criu-dump.log") + if cerr := copyFile(dumpLog, filepath.Join(work, "dump.log")); cerr != nil { +- log.G(context).Error(err) ++ log.G(ctx).Error(err) + } + return fmt.Errorf("%s path= %s", criuError(err), dumpLog) + } + return nil + } + +-func (p *Init) update(context context.Context, r *google_protobuf.Any) error { ++// Update the processes resource configuration ++func (p *Init) Update(ctx context.Context, r *google_protobuf.Any) error { ++ p.mu.Lock() ++ defer p.mu.Unlock() ++ ++ return p.initState.Update(ctx, r) ++} ++ ++func (p *Init) update(ctx context.Context, r *google_protobuf.Any) error { + var resources specs.LinuxResources + if err := json.Unmarshal(r.Value, &resources); err != nil { + return err + } +- return p.runtime.Update(context, p.id, &resources) ++ return p.runtime.Update(ctx, p.id, &resources) + } + + // Stdio of the process +diff --git a/runtime/v1/linux/proc/init_state.go b/runtime/v1/linux/proc/init_state.go +index 6a6b448d3..e83934e9c 100644 +--- a/runtime/v1/linux/proc/init_state.go ++++ b/runtime/v1/linux/proc/init_state.go +@@ -30,16 +30,20 @@ import ( + runc "github.com/containerd/go-runc" + google_protobuf "github.com/gogo/protobuf/types" + "github.com/pkg/errors" ++ "github.com/sirupsen/logrus" + ) + + type initState interface { +- proc.State +- ++ Resize(console.WinSize) error ++ Start(context.Context) error ++ Delete(context.Context) error + Pause(context.Context) error + Resume(context.Context) error + Update(context.Context, *google_protobuf.Any) error + Checkpoint(context.Context, *CheckpointConfig) error + Exec(context.Context, string, *ExecConfig) (proc.Process, error) ++ Kill(context.Context, uint32, bool) error ++ SetExited(int) + } + + type createdState struct { +@@ -61,43 +65,26 @@ func (s *createdState) transition(name string) error { + } + + func (s *createdState) Pause(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot pause task in created state") + } + + func (s *createdState) Resume(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resume task in created state") + } + +-func (s *createdState) Update(context context.Context, r *google_protobuf.Any) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- +- return s.p.update(context, r) ++func (s *createdState) Update(ctx context.Context, r *google_protobuf.Any) error { ++ return s.p.update(ctx, r) + } + +-func (s *createdState) Checkpoint(context context.Context, r *CheckpointConfig) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- ++func (s *createdState) Checkpoint(ctx context.Context, r *CheckpointConfig) error { + return errors.Errorf("cannot checkpoint a task in created state") + } + + func (s *createdState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *createdState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + if err := s.p.start(ctx); err != nil { + return err + } +@@ -105,8 +92,6 @@ func (s *createdState) Start(ctx context.Context) error { + } + + func (s *createdState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + if err := s.p.delete(ctx); err != nil { + return err + } +@@ -114,16 +99,10 @@ func (s *createdState) Delete(ctx context.Context) error { + } + + func (s *createdState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *createdState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + + if err := s.transition("stopped"); err != nil { +@@ -132,8 +111,6 @@ func (s *createdState) SetExited(status int) { + } + + func (s *createdState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + return s.p.exec(ctx, path, r) + } + +@@ -157,43 +134,26 @@ func (s *createdCheckpointState) transition(name string) error { + } + + func (s *createdCheckpointState) Pause(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot pause task in created state") + } + + func (s *createdCheckpointState) Resume(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resume task in created state") + } + +-func (s *createdCheckpointState) Update(context context.Context, r *google_protobuf.Any) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- +- return s.p.update(context, r) ++func (s *createdCheckpointState) Update(ctx context.Context, r *google_protobuf.Any) error { ++ return s.p.update(ctx, r) + } + +-func (s *createdCheckpointState) Checkpoint(context context.Context, r *CheckpointConfig) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- ++func (s *createdCheckpointState) Checkpoint(ctx context.Context, r *CheckpointConfig) error { + return errors.Errorf("cannot checkpoint a task in created state") + } + + func (s *createdCheckpointState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *createdCheckpointState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + p := s.p + sio := p.stdio + +@@ -213,7 +173,7 @@ func (s *createdCheckpointState) Start(ctx context.Context) error { + return p.runtimeError(err, "OCI runtime restore failed") + } + if sio.Stdin != "" { +- sc, err := fifo.OpenFifo(ctx, sio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) ++ sc, err := fifo.OpenFifo(context.Background(), sio.Stdin, syscall.O_WRONLY|syscall.O_NONBLOCK, 0) + if err != nil { + return errors.Wrapf(err, "failed to open stdin fifo %s", sio.Stdin) + } +@@ -247,8 +207,6 @@ func (s *createdCheckpointState) Start(ctx context.Context) error { + } + + func (s *createdCheckpointState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + if err := s.p.delete(ctx); err != nil { + return err + } +@@ -256,16 +214,10 @@ func (s *createdCheckpointState) Delete(ctx context.Context) error { + } + + func (s *createdCheckpointState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *createdCheckpointState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + + if err := s.transition("stopped"); err != nil { +@@ -274,9 +226,6 @@ func (s *createdCheckpointState) SetExited(status int) { + } + + func (s *createdCheckpointState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return nil, errors.Errorf("cannot exec in a created state") + } + +@@ -297,67 +246,42 @@ func (s *runningState) transition(name string) error { + } + + func (s *runningState) Pause(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- if err := s.p.pause(ctx); err != nil { +- return err ++ if err := s.p.runtime.Pause(ctx, s.p.id); err != nil { ++ return s.p.runtimeError(err, "OCI runtime pause failed") + } ++ + return s.transition("paused") + } + + func (s *runningState) Resume(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resume a running process") + } + +-func (s *runningState) Update(context context.Context, r *google_protobuf.Any) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- +- return s.p.update(context, r) ++func (s *runningState) Update(ctx context.Context, r *google_protobuf.Any) error { ++ return s.p.update(ctx, r) + } + + func (s *runningState) Checkpoint(ctx context.Context, r *CheckpointConfig) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.checkpoint(ctx, r) + } + + func (s *runningState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *runningState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot start a running process") + } + + func (s *runningState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot delete a running process") + } + + func (s *runningState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *runningState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + + if err := s.transition("stopped"); err != nil { +@@ -366,8 +290,6 @@ func (s *runningState) SetExited(status int) { + } + + func (s *runningState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + return s.p.exec(ctx, path, r) + } + +@@ -388,79 +310,54 @@ func (s *pausedState) transition(name string) error { + } + + func (s *pausedState) Pause(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot pause a paused container") + } + + func (s *pausedState) Resume(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- +- if err := s.p.resume(ctx); err != nil { +- return err ++ if err := s.p.runtime.Resume(ctx, s.p.id); err != nil { ++ return s.p.runtimeError(err, "OCI runtime resume failed") + } ++ + return s.transition("running") + } + +-func (s *pausedState) Update(context context.Context, r *google_protobuf.Any) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- +- return s.p.update(context, r) ++func (s *pausedState) Update(ctx context.Context, r *google_protobuf.Any) error { ++ return s.p.update(ctx, r) + } + + func (s *pausedState) Checkpoint(ctx context.Context, r *CheckpointConfig) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.checkpoint(ctx, r) + } + + func (s *pausedState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.resize(ws) + } + + func (s *pausedState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot start a paused process") + } + + func (s *pausedState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot delete a paused process") + } + + func (s *pausedState) Kill(ctx context.Context, sig uint32, all bool) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return s.p.kill(ctx, sig, all) + } + + func (s *pausedState) SetExited(status int) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + s.p.setExited(status) + ++ if err := s.p.runtime.Resume(context.Background(), s.p.id); err != nil { ++ logrus.WithError(err).Error("resuming exited container from paused state") ++ } ++ + if err := s.transition("stopped"); err != nil { + panic(err) + } + } + + func (s *pausedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return nil, errors.Errorf("cannot exec in a paused state") + } + +@@ -479,50 +376,30 @@ func (s *stoppedState) transition(name string) error { + } + + func (s *stoppedState) Pause(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot pause a stopped container") + } + + func (s *stoppedState) Resume(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resume a stopped container") + } + +-func (s *stoppedState) Update(context context.Context, r *google_protobuf.Any) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- ++func (s *stoppedState) Update(ctx context.Context, r *google_protobuf.Any) error { + return errors.Errorf("cannot update a stopped container") + } + + func (s *stoppedState) Checkpoint(ctx context.Context, r *CheckpointConfig) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot checkpoint a stopped container") + } + + func (s *stoppedState) Resize(ws console.WinSize) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot resize a stopped container") + } + + func (s *stoppedState) Start(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return errors.Errorf("cannot start a stopped process") + } + + func (s *stoppedState) Delete(ctx context.Context) error { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() + if err := s.p.delete(ctx); err != nil { + return err + } +@@ -538,8 +415,5 @@ func (s *stoppedState) SetExited(status int) { + } + + func (s *stoppedState) Exec(ctx context.Context, path string, r *ExecConfig) (proc.Process, error) { +- s.p.mu.Lock() +- defer s.p.mu.Unlock() +- + return nil, errors.Errorf("cannot exec in a stopped state") + } +diff --git a/runtime/v1/linux/proc/io.go b/runtime/v1/linux/proc/io.go +index 360662701..e620f5840 100644 +--- a/runtime/v1/linux/proc/io.go ++++ b/runtime/v1/linux/proc/io.go +@@ -114,7 +114,7 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w + if stdin == "" { + return nil + } +- f, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) ++ f, err := fifo.OpenFifo(context.Background(), stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) + if err != nil { + return fmt.Errorf("containerd-shim syscall.O_RDONLY|syscall.O_NONBLOCK: opening %s failed: %s", stdin, err) + } +diff --git a/runtime/v1/linux/proc/utils.go b/runtime/v1/linux/proc/utils.go +index d6f047cee..7312dec68 100644 +--- a/runtime/v1/linux/proc/utils.go ++++ b/runtime/v1/linux/proc/utils.go +@@ -33,6 +33,18 @@ import ( + "golang.org/x/sys/unix" + ) + ++// safePid is a thread safe wrapper for pid. ++type safePid struct { ++ sync.Mutex ++ pid int ++} ++ ++func (s *safePid) get() int { ++ s.Lock() ++ defer s.Unlock() ++ return s.pid ++} ++ + // TODO(mlaventure): move to runc package? + func getLastRuntimeError(r *runc.Runc) (string, error) { + if r.Log == "" { +diff --git a/runtime/v2/runc/service_linux.go b/runtime/v2/runc/service_linux.go +index 116167352..195c23014 100644 +--- a/runtime/v2/runc/service_linux.go ++++ b/runtime/v2/runc/service_linux.go +@@ -42,7 +42,7 @@ func (p *linuxPlatform) CopyConsole(ctx context.Context, console console.Console + } + + if stdin != "" { +- in, err := fifo.OpenFifo(ctx, stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) ++ in, err := fifo.OpenFifo(context.Background(), stdin, syscall.O_RDONLY|syscall.O_NONBLOCK, 0) + if err != nil { + return nil, err + } +diff --git a/runtime/v2/shim_unix.go b/runtime/v2/shim_unix.go +index 1a08be5d1..6738a7787 100644 +--- a/runtime/v2/shim_unix.go ++++ b/runtime/v2/shim_unix.go +@@ -28,5 +28,5 @@ import ( + ) + + func openShimLog(ctx context.Context, bundle *Bundle) (io.ReadCloser, error) { +- return fifo.OpenFifo(ctx, filepath.Join(bundle.Path, "log"), unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700) ++ return fifo.OpenFifo(ctx, filepath.Join(bundle.Path, "log"), unix.O_RDWR|unix.O_CREAT, 0700) + } +-- +2.17.1 + diff --git a/patch/0074-containerd-fix-exec-event-missing-due-to-pid-reuse.patch b/patch/0074-containerd-fix-exec-event-missing-due-to-pid-reuse.patch new file mode 100644 index 0000000..fe6a5a9 --- /dev/null +++ b/patch/0074-containerd-fix-exec-event-missing-due-to-pid-reuse.patch @@ -0,0 +1,71 @@ +From dded5a0253fbfd3c75c6d73a890049c832374545 Mon Sep 17 00:00:00 2001 +From: jingrui +Date: Sat, 20 Feb 2021 09:06:22 +0800 +Subject: [PATCH] containerd: fix exec event missing due to pid reuse + +When many exec request exit at nearly sametime, the Exit can match with +wrong process and return directly, the event for right process will lost +in this case. + +time="2021-02-19T21:10:12.250841280+08:00" level=info msg=event Pid=11623 containerID=a32a1b7923db55ebdc7483e2b9cd986e5efc750b989ad3507eb866835e8e37f4 execID=0b412ecaed98f9ea71168599a9363b8aa3b047187eadaa74973bb6c63a66118d module=libcontainerd namespace=moby topic=/tasks/exec-started +time="2021-02-19T21:10:12+08:00" level=info msg="try publish event(1) /tasks/exit &TaskExit{ContainerID:a32a1b7923db55ebdc7483e2b9cd986e5efc750b989ad3507eb866835e8e37f4,ID:0b412ecaed98f9ea71168599a9363b8aa3b047187eadaa74973bb6c63a66118d,Pid:11623,ExitStatus:0,ExitedAt:2021-02-19 21:10:12.27697416 +0800 CST m=+1893.164673481,} " +time="2021-02-19T21:11:02.944643980+08:00" level=debug msg="starting exec command 64cd335311e9b3c1c11e7360a374e3218efeb02e6578d7bc0811bad3f1820e16 in container a32a1b7923db55ebdc7483e2b9cd986e5efc750b989ad3507eb866835e8e37f4" +time="2021-02-19T21:11:06.201162360+08:00" level=debug msg="event published" ns=moby topic="/tasks/exec-started" type=containerd.events.TaskExecStarted +time="2021-02-19T21:11:57.961615320+08:00" level=warning msg="Ignoring Exit Event, no such exec command found" container=a32a1b7923db55ebdc7483e2b9cd986e5efc750b989ad3507eb866835e8e37f4 exec-id=0b412ecaed98f9ea71168599a9363b8aa3b047187eadaa74973bb6c63a66118d exec-pid=11623 + +From logs above, execID=0b412ecae with Pid=11623 exit and event +published, but new exec execID=64cd335 command reuse the Pid, but Exit +event still match previous execID=0b412ecae. so exit event for +execID=64cd335 will lost. + +Change-Id: If591a282a1cc0305758130a936ee8b92c88acc6c +Signed-off-by: jingrui +--- + runtime/v1/linux/proc/exec.go | 4 ++++ + runtime/v1/shim/service.go | 6 +++++- + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/runtime/v1/linux/proc/exec.go b/runtime/v1/linux/proc/exec.go +index ea40cb5b8..a5f40bd63 100644 +--- a/runtime/v1/linux/proc/exec.go ++++ b/runtime/v1/linux/proc/exec.go +@@ -86,6 +86,10 @@ func (e *execProcess) ExitedAt() time.Time { + } + + func (e *execProcess) SetExited(status int) { ++ e.pid.Lock() ++ e.pid.pid = -1 ++ e.pid.Unlock() ++ + e.mu.Lock() + defer e.mu.Unlock() + +diff --git a/runtime/v1/shim/service.go b/runtime/v1/shim/service.go +index 7e07ab011..7d7327cd8 100644 +--- a/runtime/v1/shim/service.go ++++ b/runtime/v1/shim/service.go +@@ -548,8 +548,13 @@ func (s *Service) checkProcesses(e runc.Exit) { + log.G(s.context).WithError(err).Error("failed to check shouldKillAll") + } + ++ match := 0 + for _, p := range s.processes { + if p.Pid() == e.Pid { ++ match++ ++ if match > 1 { ++ logrus.Warnf("exit for pid=%d match %d processes", e.Pid, match) ++ } + if ip, ok := p.(*proc.Init); ok { + ns := filepath.Base(filepath.Dir(ip.Bundle)) + events.ExitAddFile(ns, events.ExitFile(s.id, uint32(e.Pid), uint32(e.Status)), "init exited") +@@ -591,7 +596,6 @@ func (s *Service) checkProcesses(e runc.Exit) { + ExitStatus: uint32(e.Status), + ExitedAt: p.ExitedAt(), + } +- return + } + } + } +-- +2.17.1 + diff --git a/patch/0075-containerd-fix-dm-left-when-pause-contaienr-and-kill-shim.patch b/patch/0075-containerd-fix-dm-left-when-pause-contaienr-and-kill-shim.patch new file mode 100644 index 0000000..0e47373 --- /dev/null +++ b/patch/0075-containerd-fix-dm-left-when-pause-contaienr-and-kill-shim.patch @@ -0,0 +1,36 @@ +From c10041fa37568bca00a25c055ee844d38e91fa95 Mon Sep 17 00:00:00 2001 +From: chenjiankun +Date: Mon, 19 Apr 2021 17:08:09 +0800 +Subject: [PATCH] docker: fix dm left when pause contaienr and kill shim + +when shim process be killed, we will delete the runtime, but if the +status is paused, it can't be delete. So we need to resume the shim +process before delete it. +--- + runtime/v1/linux/runtime.go | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/runtime/v1/linux/runtime.go b/runtime/v1/linux/runtime.go +index 66f959d..ca36748 100644 +--- a/runtime/v1/linux/runtime.go ++++ b/runtime/v1/linux/runtime.go +@@ -541,6 +541,16 @@ func (r *Runtime) terminate(ctx context.Context, bundle *bundle, ns, id string) + } + + if !legacy.IsLegacy(id) || legacy.IsSamePid(id) { ++ ++ state, err := rt.State(ctx, id) ++ if err == nil && state.Status == "paused" { ++ logrus.Warnf("container %s status is paused, try to resume before delete", id) ++ err := rt.Resume(ctx, id) ++ if err != nil { ++ log.G(ctx).WithError(err).Errorf("runtime resume %s error", id) ++ } ++ } ++ + if err := rt.Delete(ctx, id, &runc.DeleteOpts{ + Force: true, + }); err != nil { +-- +2.23.0 + diff --git a/patch/0076-containerd-add-CGO-security-build-options.patch b/patch/0076-containerd-add-CGO-security-build-options.patch new file mode 100644 index 0000000..d465153 --- /dev/null +++ b/patch/0076-containerd-add-CGO-security-build-options.patch @@ -0,0 +1,29 @@ +From fb499f406340e142e6996b05772b5661938fefa5 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Mon, 22 Feb 2021 15:09:53 +0800 +Subject: [PATCH] containerd: add CGO security build options + +Signed-off-by: xiadanni +--- + Makefile | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/Makefile b/Makefile +index 96c2370..102db9f 100644 +--- a/Makefile ++++ b/Makefile +@@ -171,6 +171,11 @@ FORCE: + bin/%: cmd/% FORCE + mkdir -p $(BEP_DIR) + @echo "$(WHALE) $@${BINARY_SUFFIX}" ++ CGO_ENABLED=1 \ ++ CGO_CFLAGS="-fstack-protector-strong" \ ++ CGO_CPPFLAGS="-fstack-protector-strong" \ ++ CGO_LDFLAGS_ALLOW='-Wl,-z,relro,-z,now' \ ++ CGO_LDFLAGS="-Wl,-z,relro,-z,now -Wl,-z,noexecstack" \ + go build ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@${BINARY_SUFFIX} ${GO_LDFLAGS} ${GO_TAGS} ./$< + + bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 +-- +1.8.3.1 + diff --git a/patch/0077-containerd-fix-start-container-failed-with-id-exists.patch b/patch/0077-containerd-fix-start-container-failed-with-id-exists.patch new file mode 100644 index 0000000..c53b218 --- /dev/null +++ b/patch/0077-containerd-fix-start-container-failed-with-id-exists.patch @@ -0,0 +1,34 @@ +From 6936dda1f72b328cacfc29b52da780a29ef45385 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Thu, 8 Jul 2021 14:37:56 +0800 +Subject: [PATCH] containerd: fix start container failed with id exists + +reason: If container root path already exists when call runtime.Create, +we try to call runtime.Delete to cleanup it. But in case runtime.Delete +failed, root path will still exists which causes Create failed with error +"container with id exists". So remove path directly if Delete failed. + +Signed-off-by: xiadanni +--- + vendor/github.com/containerd/go-runc/runc.go | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/vendor/github.com/containerd/go-runc/runc.go b/vendor/github.com/containerd/go-runc/runc.go +index 1c96317..c089381 100644 +--- a/vendor/github.com/containerd/go-runc/runc.go ++++ b/vendor/github.com/containerd/go-runc/runc.go +@@ -159,7 +159,10 @@ func (o *CreateOpts) args() (out []string, err error) { + func (r *Runc) Create(context context.Context, id, bundle string, opts *CreateOpts) error { + if _, err := os.Stat(filepath.Join(r.Root, id)); err == nil { + logrus.Warnf("cleanup residue runtime with bundle %s root=%s", bundle, r.Root) +- r.Delete(context, id, &DeleteOpts{Force: true}) ++ if dErr := r.Delete(context, id, &DeleteOpts{Force: true}); dErr != nil { ++ logrus.Errorf("runtime force delete return err: %v, remove container root err: %v", ++ dErr, os.RemoveAll(filepath.Join(r.Root, id))) ++ } + } + + args := []string{"create", "--bundle", bundle} +-- +2.27.0 + diff --git a/patch/0078-containerd-drop-opt-package.patch b/patch/0078-containerd-drop-opt-package.patch new file mode 100644 index 0000000..807f49e --- /dev/null +++ b/patch/0078-containerd-drop-opt-package.patch @@ -0,0 +1,25 @@ +From 81d14714bb90455964eac557f9b2172d7bc3e522 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Thu, 5 Aug 2021 15:24:21 +0800 +Subject: [PATCH] [Huawei]containerd: drop opt package + +Signed-off-by: xiadanni +--- + cmd/containerd/builtins.go | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/cmd/containerd/builtins.go b/cmd/containerd/builtins.go +index b120b60..17fa9f6 100644 +--- a/cmd/containerd/builtins.go ++++ b/cmd/containerd/builtins.go +@@ -30,7 +30,6 @@ import ( + _ "github.com/containerd/containerd/services/introspection" + _ "github.com/containerd/containerd/services/leases" + _ "github.com/containerd/containerd/services/namespaces" +- _ "github.com/containerd/containerd/services/opt" + _ "github.com/containerd/containerd/services/snapshots" + _ "github.com/containerd/containerd/services/tasks" + _ "github.com/containerd/containerd/services/version" +-- +2.27.0 + diff --git a/patch/0079-containerd-bump-containerd-ttrpc-699c4e40d1.patch b/patch/0079-containerd-bump-containerd-ttrpc-699c4e40d1.patch new file mode 100644 index 0000000..f686be5 --- /dev/null +++ b/patch/0079-containerd-bump-containerd-ttrpc-699c4e40d1.patch @@ -0,0 +1,149 @@ +From 1c8a3bb488eb68523a3ae112854fcdd7326686cb Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Wed, 1 Sep 2021 07:23:17 +0800 +Subject: [PATCH] [backport]containerd:bump containerd/ttrpc + 699c4e40d1e7416e08bf7019c7ce2e9beced4636 + +full diff: https://github.com/containerd/ttrpc/compare/f02858b1457c5ca3aaec3a0803eb0d59f96e41d6...699c4e40d1e7416e08bf7019c7ce2e9beced4636 + +- containerd/ttrpc#33 Fix returns error message +- containerd/ttrpc#35 Make onclose an option + +Conflict:vendor.conf +Reference:https://github.com/containerd/containerd/commit/8c5779c32b70a0c55e1c94eb45b305897f7cf3f1 + +Signed-off-by: Sebastiaan van Stijn +Signed-off-by: xiadanni +--- + runtime/v1/shim/client/client.go | 3 +-- + runtime/v2/binary.go | 3 +-- + runtime/v2/shim.go | 3 +-- + vendor.conf | 2 +- + vendor/github.com/containerd/ttrpc/client.go | 21 ++++++++++++------- + .../github.com/containerd/ttrpc/services.go | 2 +- + 6 files changed, 19 insertions(+), 15 deletions(-) + +diff --git a/runtime/v1/shim/client/client.go b/runtime/v1/shim/client/client.go +index 48d62e537..6861df081 100644 +--- a/runtime/v1/shim/client/client.go ++++ b/runtime/v1/shim/client/client.go +@@ -299,8 +299,7 @@ func WithConnect(address string, onClose func()) Opt { + if err != nil { + return nil, nil, err + } +- client := ttrpc.NewClient(conn) +- client.OnClose(onClose) ++ client := ttrpc.NewClient(conn, ttrpc.WithOnClose(onClose)) + return shimapi.NewShimClient(client), conn, nil + } + } +diff --git a/runtime/v2/binary.go b/runtime/v2/binary.go +index 41de0d3e0..223b85300 100644 +--- a/runtime/v2/binary.go ++++ b/runtime/v2/binary.go +@@ -97,8 +97,7 @@ func (b *binary) Start(ctx context.Context) (_ *shim, err error) { + if err != nil { + return nil, err + } +- client := ttrpc.NewClient(conn) +- client.OnClose(func() { conn.Close() }) ++ client := ttrpc.NewClient(conn, ttrpc.WithOnClose(func() { _ = conn.Close() })) + return &shim{ + bundle: b.bundle, + client: client, +diff --git a/runtime/v2/shim.go b/runtime/v2/shim.go +index 982d1bb34..8e746712b 100644 +--- a/runtime/v2/shim.go ++++ b/runtime/v2/shim.go +@@ -75,8 +75,7 @@ func loadShim(ctx context.Context, bundle *Bundle, events *exchange.Exchange, rt + } + }() + +- client := ttrpc.NewClient(conn) +- client.OnClose(func() { conn.Close() }) ++ client := ttrpc.NewClient(conn, ttrpc.WithOnClose(func() { _ = conn.Close() })) + s := &shim{ + client: client, + task: task.NewTaskClient(client), +diff --git a/vendor.conf b/vendor.conf +index dbc3eecd9..0f76be3b0 100644 +--- a/vendor.conf ++++ b/vendor.conf +@@ -36,7 +36,7 @@ github.com/Microsoft/go-winio v0.4.11 + github.com/Microsoft/hcsshim v0.7.12 + google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 + golang.org/x/text 19e51611da83d6be54ddafce4a4af510cb3e9ea4 +-github.com/containerd/ttrpc 2a805f71863501300ae1976d29f0454ae003e85a ++github.com/containerd/ttrpc 699c4e40d1e7416e08bf7019c7ce2e9beced4636 + github.com/syndtr/gocapability db04d3cc01c8b54962a58ec7e491717d06cfcc16 + gotest.tools v2.1.0 + github.com/google/go-cmp v0.1.0 +diff --git a/vendor/github.com/containerd/ttrpc/client.go b/vendor/github.com/containerd/ttrpc/client.go +index e40592dd7..bc2bbde1b 100644 +--- a/vendor/github.com/containerd/ttrpc/client.go ++++ b/vendor/github.com/containerd/ttrpc/client.go +@@ -48,7 +48,15 @@ type Client struct { + err error + } + +-func NewClient(conn net.Conn) *Client { ++type ClientOpts func(c *Client) ++ ++func WithOnClose(onClose func()) ClientOpts { ++ return func(c *Client) { ++ c.closeFunc = onClose ++ } ++} ++ ++func NewClient(conn net.Conn, opts ...ClientOpts) *Client { + c := &Client{ + codec: codec{}, + conn: conn, +@@ -59,6 +67,10 @@ func NewClient(conn net.Conn) *Client { + closeFunc: func() {}, + } + ++ for _, o := range opts { ++ o(c) ++ } ++ + go c.run() + return c + } +@@ -135,11 +147,6 @@ func (c *Client) Close() error { + return nil + } + +-// OnClose allows a close func to be called when the server is closed +-func (c *Client) OnClose(closer func()) { +- c.closeFunc = closer +-} +- + type message struct { + messageHeader + p []byte +@@ -249,7 +256,7 @@ func (c *Client) recv(resp *Response, msg *message) error { + } + + if msg.Type != messageTypeResponse { +- return errors.New("unkown message type received") ++ return errors.New("unknown message type received") + } + + defer c.channel.putmbuf(msg.p) +diff --git a/vendor/github.com/containerd/ttrpc/services.go b/vendor/github.com/containerd/ttrpc/services.go +index e90963825..fe1cade5a 100644 +--- a/vendor/github.com/containerd/ttrpc/services.go ++++ b/vendor/github.com/containerd/ttrpc/services.go +@@ -76,7 +76,7 @@ func (s *serviceSet) dispatch(ctx context.Context, serviceName, methodName strin + switch v := obj.(type) { + case proto.Message: + if err := proto.Unmarshal(p, v); err != nil { +- return status.Errorf(codes.Internal, "ttrpc: error unmarshaling payload: %v", err.Error()) ++ return status.Errorf(codes.Internal, "ttrpc: error unmarshalling payload: %v", err.Error()) + } + default: + return status.Errorf(codes.Internal, "ttrpc: error unsupported request type: %T", v) +-- +2.27.0 + diff --git a/patch/0080-containerd-fix-race-access-for-mobySubcribed.patch b/patch/0080-containerd-fix-race-access-for-mobySubcribed.patch new file mode 100644 index 0000000..00d1d80 --- /dev/null +++ b/patch/0080-containerd-fix-race-access-for-mobySubcribed.patch @@ -0,0 +1,47 @@ +From fe8f7f5acac4f0fcf75218e26c1f3f874a77bf44 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Wed, 1 Sep 2021 07:29:43 +0800 +Subject: [PATCH] [Huawei]containerd:fix race access for mobySubcribed + +Signed-off-by: xiadanni +--- + events/exchange/exchange.go | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/events/exchange/exchange.go b/events/exchange/exchange.go +index 540f18054..ad642563a 100644 +--- a/events/exchange/exchange.go ++++ b/events/exchange/exchange.go +@@ -19,6 +19,7 @@ package exchange + import ( + "context" + "strings" ++ "sync/atomic" + "time" + + "github.com/containerd/containerd/errdefs" +@@ -49,10 +50,10 @@ func NewExchange() *Exchange { + var _ events.Publisher = &Exchange{} + var _ events.Forwarder = &Exchange{} + var _ events.Subscriber = &Exchange{} +-var mobySubcribed = false ++var mobySubcribed = int32(0) + + func MobySubscribed() bool { +- return mobySubcribed ++ return atomic.LoadInt32(&mobySubcribed) == 1 + } + + // Forward accepts an envelope to be direcly distributed on the exchange. +@@ -170,7 +171,7 @@ func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *even + for _, s := range fs { + if !MobySubscribed() && s == "namespace==moby,topic~=|^/tasks/|" { + queue.Namespace = "moby" +- mobySubcribed = true ++ atomic.StoreInt32(&mobySubcribed, 1) + } + } + +-- +2.27.0 + diff --git a/patch/0081-containerd-improve-log-for-debugging.patch b/patch/0081-containerd-improve-log-for-debugging.patch new file mode 100644 index 0000000..d4708ad --- /dev/null +++ b/patch/0081-containerd-improve-log-for-debugging.patch @@ -0,0 +1,137 @@ +From 003a26f92ccfd6f296910874ed9ad55d652413cc Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Fri, 29 Oct 2021 16:37:28 +0800 +Subject: [PATCH] containerd: improve log for debugging + +add following logs for debugging +1. return event publish errors +2. redirect is used to make sure that containerd still can read the log + of shim after restart + +Conflict:NA +Reference: +https://github.com/containerd/containerd/pull/3179/commits/74eb0dc81221bffc192a349cf8b14fe7947b7a73 +https://github.com/containerd/containerd/pull/5293/commits/45df696bf3fe3eda15bbf0f2c00ddc2cfeddcdcc +https://github.com/containerd/containerd/commit/fbb80b9510db14a95b8ffa6c7842666ecf520489 + +Signed-off-by: xiadanni +--- + cmd/containerd-shim/main_unix.go | 23 ++++++++++++++++++++--- + runtime/v1/linux/runtime.go | 1 + + runtime/v1/shim/client/client.go | 22 ++++++++++------------ + 3 files changed, 31 insertions(+), 15 deletions(-) + +diff --git a/cmd/containerd-shim/main_unix.go b/cmd/containerd-shim/main_unix.go +index 3a5bb6170..a07932cef 100644 +--- a/cmd/containerd-shim/main_unix.go ++++ b/cmd/containerd-shim/main_unix.go +@@ -61,6 +61,12 @@ var ( + criuFlag string + systemdCgroupFlag bool + containerdBinaryFlag string ++ ++ bufPool = sync.Pool{ ++ New: func() interface{} { ++ return bytes.NewBuffer(nil) ++ }, ++ } + ) + + func init() { +@@ -101,6 +107,10 @@ func main() { + stderr.Close() + }() + ++ // redirect the following output into fifo to make sure that containerd ++ // still can read the log after restart ++ logrus.SetOutput(stdout) ++ + if err := executeShim(); err != nil { + fmt.Fprintf(os.Stderr, "containerd-shim: %s\n", err) + os.Exit(1) +@@ -110,7 +120,7 @@ func main() { + // If containerd server process dies, we need the shim to keep stdout/err reader + // FDs so that Linux does not SIGPIPE the shim process if it tries to use its end of + // these pipes. +-func openStdioKeepAlivePipes(dir string) (io.ReadCloser, io.ReadCloser, error) { ++func openStdioKeepAlivePipes(dir string) (io.ReadWriteCloser, io.ReadWriteCloser, error) { + background := context.Background() + keepStdoutAlive, err := shimlog.OpenShimStdoutLog(background, dir) + if err != nil { +@@ -287,16 +297,23 @@ func (l *remoteEventsPublisher) doPublish(ctx context.Context, topic string, eve + } + cmd := exec.CommandContext(ctx, containerdBinaryFlag, "--address", l.address, "publish", "--topic", topic, "--namespace", ns) + cmd.Stdin = bytes.NewReader(data) ++ b := bufPool.Get().(*bytes.Buffer) ++ defer func() { ++ b.Reset() ++ bufPool.Put(b) ++ }() ++ cmd.Stdout = b ++ cmd.Stderr = b + c, err := shim.Default.Start(cmd) + if err != nil { + return err + } + status, err := shim.Default.Wait(cmd, c) + if err != nil { +- return err ++ return errors.Wrapf(err, "failed to publish event: %s", b.String()) + } + if status != 0 { +- return errors.New("failed to publish event") ++ return errors.Errorf("failed to publish event: %s", b.String()) + } + return nil + } +diff --git a/runtime/v1/linux/runtime.go b/runtime/v1/linux/runtime.go +index ca3674808..eb3927305 100644 +--- a/runtime/v1/linux/runtime.go ++++ b/runtime/v1/linux/runtime.go +@@ -379,6 +379,7 @@ func (r *Runtime) loadTasks(ctx context.Context, ns string) ([]*Task, error) { + log.G(ctx).Infof("load-task %s/%s/%s Pid=%d", r.state, ns, id, pid) + shimExit := make(chan struct{}) + s, err := bundle.NewShimClient(ctx, ns, ShimConnect(r.config, func() { ++ log.G(ctx).WithField("id", id).Info("shim reaped") + close(shimExit) + if _, err := r.tasks.Get(ctx, id); err != nil { + // Task was never started or was already successfully deleted +diff --git a/runtime/v1/shim/client/client.go b/runtime/v1/shim/client/client.go +index eafb0d712..6861df081 100644 +--- a/runtime/v1/shim/client/client.go ++++ b/runtime/v1/shim/client/client.go +@@ -77,21 +77,19 @@ func WithStart(binary, address, daemonAddress, cgroup string, debug bool, exitHa + + var stdoutLog io.ReadWriteCloser + var stderrLog io.ReadWriteCloser +- if debug { +- stdoutLog, err = v1.OpenShimStdoutLog(ctx, config.WorkDir) +- if err != nil { +- return nil, nil, errors.Wrapf(err, "failed to create stdout log") +- } +- +- stderrLog, err = v1.OpenShimStderrLog(ctx, config.WorkDir) +- if err != nil { +- return nil, nil, errors.Wrapf(err, "failed to create stderr log") +- } ++ stdoutLog, err = v1.OpenShimStdoutLog(ctx, config.WorkDir) ++ if err != nil { ++ return nil, nil, errors.Wrapf(err, "failed to create stdout log") ++ } + +- go io.Copy(os.Stdout, stdoutLog) +- go io.Copy(os.Stderr, stderrLog) ++ stderrLog, err = v1.OpenShimStderrLog(ctx, config.WorkDir) ++ if err != nil { ++ return nil, nil, errors.Wrapf(err, "failed to create stderr log") + } + ++ go io.Copy(os.Stdout, stdoutLog) ++ go io.Copy(os.Stderr, stderrLog) ++ + if err := writeFile(filepath.Join(config.Path, "address"), address); err != nil { + return nil, nil, err + } +-- +2.27.0 + diff --git a/patch/0068-containerd-reduce-permissions-for-bundle-dir-to-fix-.patch b/patch/0082-containerd-reduce-permissions-for-bundle-di.patch similarity index 88% rename from patch/0068-containerd-reduce-permissions-for-bundle-dir-to-fix-.patch rename to patch/0082-containerd-reduce-permissions-for-bundle-di.patch index 85cf5dd..fbac4f8 100644 --- a/patch/0068-containerd-reduce-permissions-for-bundle-dir-to-fix-.patch +++ b/patch/0082-containerd-reduce-permissions-for-bundle-di.patch @@ -1,24 +1,23 @@ -From 6029940872e30dac2c1bff9ff7dce3c3ab7576c8 Mon Sep 17 00:00:00 2001 +From fe70d9e0048502addcbeea5399f2da554a14bd78 Mon Sep 17 00:00:00 2001 From: xiadanni -Date: Fri, 5 Nov 2021 09:56:29 +0800 -Subject: [PATCH] containerd:reduce permissions for bundle dir to fix +Date: Tue, 9 Nov 2021 16:25:09 +0800 +Subject: [PATCH] [Backport]containerd:reduce permissions for bundle dir to fix CVE-2021-41103 -upstream: -https://github.com/containerd/containerd/commit/6886c6a2ec0c70dde1aa64e77b64a5ad47b983c3 -v1 runtime: reduce permissions for bundle dir +reduce permissions for bundle dir +reduce permissions on plugin directories +fix CVE-2021-41103 +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/6886c6a2ec0c70dde1aa64e77b64a5ad47b983c3 https://github.com/containerd/containerd/commit/7c621e1fcc08bcf5a1a48b837342cc22eada1685 -btrfs: reduce permissions on plugin directories - -Signed-off-by: xiadanni --- runtime/v1/linux/bundle.go | 56 +++++++++++++++++++++++++++++++++++++- snapshots/btrfs/btrfs.go | 8 ++++-- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/runtime/v1/linux/bundle.go b/runtime/v1/linux/bundle.go -index 0442246..90a1086 100644 +index 0442246f9..90a10862e 100644 --- a/runtime/v1/linux/bundle.go +++ b/runtime/v1/linux/bundle.go @@ -20,6 +20,7 @@ package linux @@ -113,7 +112,7 @@ index 0442246..90a1086 100644 id string path string diff --git a/snapshots/btrfs/btrfs.go b/snapshots/btrfs/btrfs.go -index a89b551..da6f822 100644 +index a89b55129..da6f8220e 100644 --- a/snapshots/btrfs/btrfs.go +++ b/snapshots/btrfs/btrfs.go @@ -63,11 +63,15 @@ type snapshotter struct { diff --git a/patch/0083-containerd-fix-publish-command-wait-block-for.patch b/patch/0083-containerd-fix-publish-command-wait-block-for.patch new file mode 100644 index 0000000..ec9f783 --- /dev/null +++ b/patch/0083-containerd-fix-publish-command-wait-block-for.patch @@ -0,0 +1,25 @@ +From 31cd7bb5147c42384ffd28e9a64f0c5d5c4f7500 Mon Sep 17 00:00:00 2001 +From: chenjiankun +Date: Wed, 10 Nov 2021 16:10:37 +0800 +Subject: [PATCH] containerd: fix publish command wait block forever + +--- + cmd/containerd-shim/main_unix.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cmd/containerd-shim/main_unix.go b/cmd/containerd-shim/main_unix.go +index a07932c..37b621e 100644 +--- a/cmd/containerd-shim/main_unix.go ++++ b/cmd/containerd-shim/main_unix.go +@@ -308,7 +308,7 @@ func (l *remoteEventsPublisher) doPublish(ctx context.Context, topic string, eve + if err != nil { + return err + } +- status, err := shim.Default.Wait(cmd, c) ++ status, err := shim.Default.WaitTimeout(cmd, c, 30) + if err != nil { + return errors.Wrapf(err, "failed to publish event: %s", b.String()) + } +-- +2.27.0 + diff --git a/patch/0084-containerd-treat-manifest-provided-URLs-differently.patch b/patch/0084-containerd-treat-manifest-provided-URLs-differently.patch new file mode 100644 index 0000000..717e4a1 --- /dev/null +++ b/patch/0084-containerd-treat-manifest-provided-URLs-differently.patch @@ -0,0 +1,65 @@ +From eb6ab2e84ab184321bd649b4def182f93e62b6df Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Mon, 24 Jan 2022 19:03:30 +0800 +Subject: [PATCH] [Backport]treat manifest provided URLs differently + +fix CVE-2020-15157 + +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/1ead8d9deb3b175bf40413b8c47b3d19c2262726 +https://github.com/containerd/containerd/commit/abbb17959f55bbb9b7eb37f965d7dad2f4ea8744 + +Signed-off-by: xiadanni +--- + remotes/docker/fetcher.go | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/remotes/docker/fetcher.go b/remotes/docker/fetcher.go +index 4a2ce3c39..00e7a47c6 100644 +--- a/remotes/docker/fetcher.go ++++ b/remotes/docker/fetcher.go +@@ -56,6 +56,26 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R + } + + return newHTTPReadSeeker(desc.Size, func(offset int64) (io.ReadCloser, error) { ++ if len(desc.URLs) > 0 { ++ db := *r.dockerBase ++ // Remove authorizer to avoid authentication when ++ // connecting to manifest provided URLs. ++ // Prevents https://github.com/containerd/containerd/security/advisories/GHSA-742w-89gc-8m9c ++ db.auth = nil ++ nr := dockerFetcher{ ++ dockerBase: &db, ++ } ++ for _, u := range desc.URLs { ++ log.G(ctx).WithField("url", u).Debug("trying alternative url") ++ rc, err := nr.open(ctx, u, desc.MediaType, offset) ++ if err != nil { ++ log.G(ctx).WithField("error", err).Debug("error trying url") ++ continue // try one of the other urls. ++ } ++ ++ return rc, nil ++ } ++ } + for _, u := range urls { + rc, err := r.open(ctx, u, desc.MediaType, offset) + if err != nil { +@@ -142,14 +162,6 @@ func (r dockerFetcher) open(ctx context.Context, u, mediatype string, offset int + func (r *dockerFetcher) getV2URLPaths(ctx context.Context, desc ocispec.Descriptor) ([]string, error) { + var urls []string + +- if len(desc.URLs) > 0 { +- // handle fetch via external urls. +- for _, u := range desc.URLs { +- log.G(ctx).WithField("url", u).Debug("adding alternative url") +- urls = append(urls, u) +- } +- } +- + switch desc.MediaType { + case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList, + images.MediaTypeDockerSchema1Manifest, +-- +2.27.0 + diff --git a/patch/0085-containerd-Use-chmod-path-for-checking-symlink.patch b/patch/0085-containerd-Use-chmod-path-for-checking-symlink.patch new file mode 100644 index 0000000..bc4cf4f --- /dev/null +++ b/patch/0085-containerd-Use-chmod-path-for-checking-symlink.patch @@ -0,0 +1,30 @@ +From 90a3fd55136fb18641c8221792b013ee1dbc17f5 Mon Sep 17 00:00:00 2001 +From: xiadanni +Date: Mon, 24 Jan 2022 19:15:14 +0800 +Subject: [PATCH] [Backport]Use chmod path for checking symlink + +fix CVE-2021-32760 +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/03aa748c11663e87a72fab92b7ab7c88c28bf13e + +Signed-off-by: xiadanni +--- + archive/tar_unix.go | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/archive/tar_unix.go b/archive/tar_unix.go +index 022dd6d4f..7f3857c7d 100644 +--- a/archive/tar_unix.go ++++ b/archive/tar_unix.go +@@ -127,7 +127,7 @@ func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error { + + func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error { + if hdr.Typeflag == tar.TypeLink { +- if fi, err := os.Lstat(hdr.Linkname); err == nil && (fi.Mode()&os.ModeSymlink == 0) { ++ if fi, err := os.Lstat(path); err == nil && (fi.Mode()&os.ModeSymlink == 0) { + if err := os.Chmod(path, hdrInfo.Mode()); err != nil { + return err + } +-- +2.27.0 + diff --git a/patch/0086-containerd-Add-lock-for-ListPids.patch b/patch/0086-containerd-Add-lock-for-ListPids.patch new file mode 100644 index 0000000..9bfc877 --- /dev/null +++ b/patch/0086-containerd-Add-lock-for-ListPids.patch @@ -0,0 +1,31 @@ +From 9a92dd95046003cd661f8cd76429b2e424907a2a Mon Sep 17 00:00:00 2001 +From: Vanient +Date: Mon, 21 Mar 2022 06:57:02 +0800 +Subject: [PATCH] [Backport]containerd: Add lock for ListPids + +Add the missing locks in ListPids +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/fcf3b275fcd404ddf5fe75d5629d2168742ec0d3 + +Signed-off-by: Vanient +--- + runtime/v1/shim/service.go | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/runtime/v1/shim/service.go b/runtime/v1/shim/service.go +index 7d7327cd8..435f02e3c 100644 +--- a/runtime/v1/shim/service.go ++++ b/runtime/v1/shim/service.go +@@ -434,6 +434,9 @@ func (s *Service) ListPids(ctx context.Context, r *shimapi.ListPidsRequest) (*sh + return nil, errdefs.ToGRPC(err) + } + var processes []*task.ProcessInfo ++ ++ s.mu.Lock() ++ defer s.mu.Unlock() + for _, pid := range pids { + pInfo := task.ProcessInfo{ + Pid: pid, +-- +2.27.0 + diff --git a/patch/0069-containerd-Use-fs.RootPath-when-mounting-vo.patch b/patch/0087-containerd-Use-fs.RootPath-when-mounting-vo.patch similarity index 87% rename from patch/0069-containerd-Use-fs.RootPath-when-mounting-vo.patch rename to patch/0087-containerd-Use-fs.RootPath-when-mounting-vo.patch index 130d407..4124523 100644 --- a/patch/0069-containerd-Use-fs.RootPath-when-mounting-vo.patch +++ b/patch/0087-containerd-Use-fs.RootPath-when-mounting-vo.patch @@ -1,10 +1,10 @@ From 53c45a7abaea09e60e0175f192742c74d1be60e2 Mon Sep 17 00:00:00 2001 From: Vanient Date: Thu, 31 Mar 2022 21:30:15 +0800 -Subject: [PATCH] containerd:Use fs.RootPath when mounting volumes +Subject: [PATCH] [Backport]containerd:Use fs.RootPath when mounting volumes -fix CVE-2022-23648 -upstream:https://github.com/containerd/containerd/commit/3406af86394c2426ce7f55d5f52be2b79f456211 +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/3406af86394c2426ce7f55d5f52be2b79f456211 Signed-off-by: Vanient --- diff --git a/patch/0088-images-validate-document-type-before-unmarshal.patch b/patch/0088-images-validate-document-type-before-unmarshal.patch new file mode 100644 index 0000000..f4998f6 --- /dev/null +++ b/patch/0088-images-validate-document-type-before-unmarshal.patch @@ -0,0 +1,117 @@ +From e3e70b398ff362182797e2d73372f8f654ba9383 Mon Sep 17 00:00:00 2001 +From: Vanient +Date: Thu, 9 Jun 2022 10:45:47 +0800 +Subject: [PATCH 1/2] images: validate document type before unmarshal + +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/eb9ba7ed8d46d48fb22362f9d91fff6fb837e37e + +Signed-off-by: Vanient +--- + images/image.go | 55 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 55 insertions(+) + +diff --git a/images/image.go b/images/image.go +index f72684d82..ad12fe971 100644 +--- a/images/image.go ++++ b/images/image.go +@@ -19,6 +19,7 @@ package images + import ( + "context" + "encoding/json" ++ "fmt" + "sort" + "strings" + "time" +@@ -154,6 +155,10 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc + return nil, err + } + ++ if err := validateMediaType(p, desc.MediaType); err != nil { ++ return nil, errors.Wrapf(err, "manifest: invalid desc %s", desc.Digest) ++ } ++ + var manifest ocispec.Manifest + if err := json.Unmarshal(p, &manifest); err != nil { + return nil, err +@@ -194,6 +199,10 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc + return nil, err + } + ++ if err := validateMediaType(p, desc.MediaType); err != nil { ++ return nil, errors.Wrapf(err, "manifest: invalid desc %s", desc.Digest) ++ } ++ + var idx ocispec.Index + if err := json.Unmarshal(p, &idx); err != nil { + return nil, err +@@ -335,6 +344,10 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr + return nil, err + } + ++ if err := validateMediaType(p, desc.MediaType); err != nil { ++ return nil, errors.Wrapf(err, "children: invalid desc %s", desc.Digest) ++ } ++ + // TODO(stevvooe): We just assume oci manifest, for now. There may be + // subtle differences from the docker version. + var manifest ocispec.Manifest +@@ -350,6 +363,10 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr + return nil, err + } + ++ if err := validateMediaType(p, desc.MediaType); err != nil { ++ return nil, errors.Wrapf(err, "children: invalid desc %s", desc.Digest) ++ } ++ + var index ocispec.Index + if err := json.Unmarshal(p, &index); err != nil { + return nil, err +@@ -371,6 +388,44 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr + return descs, nil + } + ++// unknownDocument represents a manifest, manifest list, or index that has not ++// yet been validated. ++type unknownDocument struct { ++ MediaType string `json:"mediaType,omitempty"` ++ Config json.RawMessage `json:"config,omitempty"` ++ Layers json.RawMessage `json:"layers,omitempty"` ++ Manifests json.RawMessage `json:"manifests,omitempty"` ++ FSLayers json.RawMessage `json:"fsLayers,omitempty"` // schema 1 ++} ++ ++// validateMediaType returns an error if the byte slice is invalid JSON or if ++// the media type identifies the blob as one format but it contains elements of ++// another format. ++func validateMediaType(b []byte, mt string) error { ++ var doc unknownDocument ++ if err := json.Unmarshal(b, &doc); err != nil { ++ return err ++ } ++ if len(doc.FSLayers) != 0 { ++ return fmt.Errorf("media-type: schema 1 not supported") ++ } ++ switch mt { ++ case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: ++ if len(doc.Manifests) != 0 || ++ doc.MediaType == MediaTypeDockerSchema2ManifestList || ++ doc.MediaType == ocispec.MediaTypeImageIndex { ++ return fmt.Errorf("media-type: expected manifest but found index (%s)", mt) ++ } ++ case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: ++ if len(doc.Config) != 0 || len(doc.Layers) != 0 || ++ doc.MediaType == MediaTypeDockerSchema2Manifest || ++ doc.MediaType == ocispec.MediaTypeImageManifest { ++ return fmt.Errorf("media-type: expected index but found manifest (%s)", mt) ++ } ++ } ++ return nil ++} ++ + // RootFS returns the unpacked diffids that make up and images rootfs. + // + // These are used to verify that a set of layers unpacked to the expected +-- +2.27.0 + diff --git a/patch/0089-schema1-reject-ambiguous-documents.patch b/patch/0089-schema1-reject-ambiguous-documents.patch new file mode 100644 index 0000000..d03ec24 --- /dev/null +++ b/patch/0089-schema1-reject-ambiguous-documents.patch @@ -0,0 +1,43 @@ +From 7a294fa5d943401ed3cb9149f69f1d12f372c374 Mon Sep 17 00:00:00 2001 +From: Vanient +Date: Thu, 9 Jun 2022 10:48:09 +0800 +Subject: [PATCH 2/2] schema1: reject ambiguous documents + +Conflict:NA +Reference:https://github.com/containerd/containerd/commit/70c88f507579277ab7af23b06666e3b57d4b4f2d + +Signed-off-by: Vanient +--- + remotes/docker/schema1/converter.go | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/remotes/docker/schema1/converter.go b/remotes/docker/schema1/converter.go +index 766c24a26..c618a33d5 100644 +--- a/remotes/docker/schema1/converter.go ++++ b/remotes/docker/schema1/converter.go +@@ -250,6 +250,9 @@ func (c *Converter) fetchManifest(ctx context.Context, desc ocispec.Descriptor) + if err := json.Unmarshal(b, &m); err != nil { + return err + } ++ if len(m.Manifests) != 0 || len(m.Layers) != 0 { ++ return errors.New("converter: expected schema1 document but found extra keys") ++ } + c.pulledManifest = &m + + return nil +@@ -466,8 +469,10 @@ type history struct { + } + + type manifest struct { +- FSLayers []fsLayer `json:"fsLayers"` +- History []history `json:"history"` ++ FSLayers []fsLayer `json:"fsLayers"` ++ History []history `json:"history"` ++ Layers json.RawMessage `json:"layers,omitempty"` // OCI manifest ++ Manifests json.RawMessage `json:"manifests,omitempty"` // OCI index + } + + type v1History struct { +-- +2.27.0 + diff --git a/patch/0090-containerd-put-get-pid-lock-after-set-process-exited-to-.patch b/patch/0090-containerd-put-get-pid-lock-after-set-process-exited-to-.patch new file mode 100644 index 0000000..7220422 --- /dev/null +++ b/patch/0090-containerd-put-get-pid-lock-after-set-process-exited-to-.patch @@ -0,0 +1,37 @@ +From a6c7265aa68fca3a5023ad2b399799db583fffeb Mon Sep 17 00:00:00 2001 +From: zhangsong +Date: Tue, 14 Jun 2022 10:25:47 +0800 +Subject: [PATCH] containerd: put get pid lock after set process exited to avoid + deadlock. + +Signed-off-by: zhangsong +--- + runtime/v1/linux/proc/exec.go | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/runtime/v1/linux/proc/exec.go b/runtime/v1/linux/proc/exec.go +index a5f40bd..ff967b5 100644 +--- a/runtime/v1/linux/proc/exec.go ++++ b/runtime/v1/linux/proc/exec.go +@@ -86,14 +86,14 @@ func (e *execProcess) ExitedAt() time.Time { + } + + func (e *execProcess) SetExited(status int) { +- e.pid.Lock() +- e.pid.pid = -1 +- e.pid.Unlock() +- + e.mu.Lock() + defer e.mu.Unlock() + + e.execState.SetExited(status) ++ ++ e.pid.Lock() ++ e.pid.pid = -1 ++ e.pid.Unlock() + } + + func (e *execProcess) setExited(status int) { +-- +2.27.0 + diff --git a/patch/0091-containerd-add-CGO-sercurity-build-options.patch b/patch/0091-containerd-add-CGO-sercurity-build-options.patch new file mode 100644 index 0000000..29ec5ab --- /dev/null +++ b/patch/0091-containerd-add-CGO-sercurity-build-options.patch @@ -0,0 +1,38 @@ +From f7d5384097fde1e448649fcacde0dd05b7f2e967 Mon Sep 17 00:00:00 2001 +From: zjw +Date: Mon, 20 Jun 2022 20:08:24 +0800 +Subject: [PATCH] containerd: containerd and containerd-shim add CGO security build options + +--- + Makefile | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/Makefile b/Makefile +index 49a90e6..2bc5dd5 100644 +--- a/Makefile ++++ b/Makefile +@@ -172,8 +172,8 @@ bin/%: cmd/% FORCE + mkdir -p $(BEP_DIR) + @echo "$(WHALE) $@${BINARY_SUFFIX}" + CGO_ENABLED=1 \ +- CGO_CFLAGS="-fstack-protector-strong" \ +- CGO_CPPFLAGS="-fstack-protector-strong" \ ++ CGO_CFLAGS="-fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2" \ ++ CGO_CPPFLAGS="-fstack-protector-strong -D_FORTIFY_SOURCE=2 -O2" \ + CGO_LDFLAGS_ALLOW='-Wl,-z,relro,-z,now' \ + CGO_LDFLAGS="-Wl,-z,relro,-z,now -Wl,-z,noexecstack" \ + go build ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@${BINARY_SUFFIX} ${GO_LDFLAGS} ${GO_TAGS} ./$< +@@ -181,8 +181,8 @@ bin/%: cmd/% FORCE + bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 + @echo "$(WHALE) bin/containerd-shim" + CGO_ENABLED=1 \ +- CGO_CFLAGS="-fstack-protector-strong -fPIE" \ +- CGO_CPPFLAGS="-fstack-protector-strong -fPIE" \ ++ CGO_CFLAGS="-fstack-protector-strong -fPIE -D_FORTIFY_SOURCE=2 -O2" \ ++ CGO_CPPFLAGS="-fstack-protector-strong -fPIE -D_FORTIFY_SOURCE=2 -O2" \ + CGO_LDFLAGS_ALLOW='-Wl,-z,relro,-z,now' \ + CGO_LDFLAGS="-Wl,-z,relro,-z,now -Wl,-z,noexecstack" \ + go build -buildmode=pie ${GO_BUILD_FLAGS} -o bin/containerd-shim ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim +-- +2.30.0 + diff --git a/patch/0070-containerd-Limit-the-response-size-of-ExecSync.patch b/patch/0092-containerd-Limit-the-response-size-of-ExecSync.patch similarity index 100% rename from patch/0070-containerd-Limit-the-response-size-of-ExecSync.patch rename to patch/0092-containerd-Limit-the-response-size-of-ExecSync.patch diff --git a/series.conf b/series.conf index 5586f87..dffd7b6 100644 --- a/series.conf +++ b/series.conf @@ -69,6 +69,29 @@ patch/0064-containerd-check-task-list-to-avoid-unnecessary-clea.patch patch/0065-containerd-fix-dead-loop.patch patch/0066-containerd-cleanup-dangling-shim-by-brand-new-context.patch patch/0067-containerd-fix-potential-panic-for-task-in-unknown-state.patch -patch/0068-containerd-reduce-permissions-for-bundle-dir-to-fix-.patch -patch/0069-containerd-Use-fs.RootPath-when-mounting-vo.patch -patch/0070-containerd-Limit-the-response-size-of-ExecSync.patch +patch/0068-containerd-compile-option-compliance.patch +patch/0069-containerd-add-check-in-spec.patch +patch/0070-containerd-kill-container-init-process-if-runc-start.patch +patch/0071-containerd-fix-containerd-shim-residual-when-kill-co.patch +patch/0072-containerd-fix-deadlock-on-commit-error.patch +patch/0073-containerd-backport-upstream-patches.patch +patch/0074-containerd-fix-exec-event-missing-due-to-pid-reuse.patch +patch/0075-containerd-fix-dm-left-when-pause-contaienr-and-kill-shim.patch +patch/0076-containerd-add-CGO-security-build-options.patch +patch/0077-containerd-fix-start-container-failed-with-id-exists.patch +patch/0078-containerd-drop-opt-package.patch +patch/0079-containerd-bump-containerd-ttrpc-699c4e40d1.patch +patch/0080-containerd-fix-race-access-for-mobySubcribed.patch +patch/0081-containerd-improve-log-for-debugging.patch +patch/0082-containerd-reduce-permissions-for-bundle-di.patch +patch/0083-containerd-fix-publish-command-wait-block-for.patch +patch/0084-containerd-treat-manifest-provided-URLs-differently.patch +patch/0085-containerd-Use-chmod-path-for-checking-symlink.patch +patch/0086-containerd-Add-lock-for-ListPids.patch +patch/0087-containerd-Use-fs.RootPath-when-mounting-vo.patch +patch/0088-images-validate-document-type-before-unmarshal.patch +patch/0089-schema1-reject-ambiguous-documents.patch +patch/0090-containerd-put-get-pid-lock-after-set-process-exited-to-.patch +patch/0091-containerd-add-CGO-sercurity-build-options.patch +patch/0092-containerd-Limit-the-response-size-of-ExecSync.patch + -- Gitee