114 Commits
Author SHA1 Message Date
Craig Gumbley 40c6ab6d53 runtime/v2: avoid symlink for bundle work dir on Windows
Creating symlinks on Windows requires administrator privileges or
Developer Mode, so NewBundle fails with "A required privilege is not
held by the client" when containerd creates a task without them.

Replace the direct os.Symlink and os.Readlink calls with platform
specific helpers. On non-Windows platforms they keep the existing
symlink behaviour. On Windows, createWorkLink creates a directory
junction using go-winio's reparse point encoding, which does not need
elevated privileges. os.Readlink resolves both symlinks and junctions,
so resolveWorkLink uses it on both platforms.

createWorkLink closes the directory handle before removing the
half-created junction directory on failure. The handle is opened
without sharing, so removing the directory while it is still open would
fail.

Signed-off-by: Craig Gumbley <craiggumbley@gmail.com>
Signed-off-by: Eric Curtin <eric.curtin@docker.com>
Assisted-by: OpenCode (anthropic/claude-sonnet-5-5)
2026-11-02 14:04:39 +00:00
Wei Fu 61ddbd7219 Revert "fix: propagate context deadline exceeded error properly"
This reverts commit f078cebbd1.

Propagating State deadline errors causes Get to fail and List to omit
tasks when a shim is temporarily unresponsive, such as during slow
cleanup in Delete. A timeout does not mean the task no longer exists,
and omitting it makes container lifecycle management harder for clients
and CRI.

Restore the previous behavior of returning UNKNOWN on State timeouts,
so tasks remain visible and callers can reconcile their state.

Refs: https://github.com/containerd/containerd/pull/14380#pullrequestreview-5689176711

Signed-off-by: Wei Fu <fuweid89@gmail.com>
2026-10-29 10:25:20 -04:00
Sebastiaan van Stijn ebe078365d core: fix perfsprint linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-17 10:45:39 +02:00
Mike Brown 3e7aecb8b4 minimal in-memory sandbox shim
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
2026-09-16 17:07:40 -05:00
Samuel Karp c176f185b0 pkg/oci: mask thermal interrupt info
Mask /proc/interrupts and /sys/devices/system/cpu/cpu<x>/thermal_throttle
inside Linux containers by default, matching moby, kubernetes, podman,
buildah, and cri-o.

See also: https://github.com/kubernetes/kubernetes/issues/138512#issuecomment-4473867774

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-09-09 17:03:16 -07:00
Maksym Pavlenko 793cee6195 Merge pull request #13309 from ningmingxiao/fix_leak
runtime: invoke shim.Delete when connection is closed
2026-09-02 23:47:47 +00:00
Maksym Pavlenko fe55f3aef4 Merge pull request #13993 from ningmingxiao/fix_restart2
fix: fix incorrect restart=always restart logic
2026-09-01 17:16:12 +00:00
ningmingxiao e49a475d4a runtime: invoke shim.Delete when connection is closed
Signed-off-by: ningmingxiao <ning.mingxiao@zte.com.cn>
2026-08-28 08:58:23 -05:00
Wei Fu 24dc6900ec runtime: make task.Delete API retriable
To make task.Delete retriable, this patch caches the delete result in
memory after the shim successfully deletes the task. If a later shutdown
attempt fails, a subsequent Delete retry can complete cleanup and return the
cached exit information.

If containerd restarts after deleting the task, the in-memory cache is lost,
and containerd will publish TaskExit and TaskDelete events again to
subscribers. Currently, the exit status returned by shim-delete is always
137. In a follow-up, containerd-shim-runc-v2 should store the actual exit
status in the state directory, so that shim-delete can reuse it instead of
returning a hard-coded value.

Implements: #8981

Signed-off-by: Wei Fu <fuweid89@gmail.com>
2026-08-26 18:10:43 -04:00
Derek McGowan 1ff0c13859 runtime/v2: migrate early adopters of the deprecated annotation
Kata's EROFS snapshotter shim set containerd.io/runtime-allow-mounts
before the MountCapabilities bootstrap extension existed
(https://github.com/kata-containers/kata-containers/pull/12763), so
removing the annotation outright would break it and anyone else who
adopted it early with no migration window.

Rather than keep the annotation as a first-class, permanently
supported mechanism, confine falling back to it in
task_mounts_deprecated.go: when a shim's bootstrap result carries no
MountCapabilities extension, its runtime name is checked against the
annotation as a migration path, with the result cached per runtime
name for the life of the daemon, same as the removed mechanism did.
Two runtimes known to never set it, runc.v2 and runhcs.v1, are
skipped outright rather than queried.

The extension stays authoritative whenever a shim provides it: this
fallback only runs in its absence, and is confined to one file so it
can be deleted outright once known early adopters have migrated.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan d3cc320650 runtime/v2: propagate shim mount capabilities to sandbox members
When a container joins an existing sandbox via a Task API address supplied
directly by the sandbox controller (rather than by restoring
bootstrap.json), ShimManager.Start synthesized a BootstrapResult carrying
only the version, protocol and address. A shim that advertised
MountCapabilities at sandbox startup was therefore treated as if it had
advertised nothing for every container that joins the sandbox this way,
silently ignoring mount handling it explicitly claimed.

Recover the extensions from the sandbox's shim instance, which containerd
already holds in memory, via the existing shimCapabilities interface. This
is best effort: an external sandboxer whose shim instance containerd does
not track degrades to no extensions rather than failing sandbox startup,
matching today's behavior.

Reported independently by fuweid and Copilot on containerd/containerd#14002.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan e8963fc32b runtime/v2: negotiate mount capabilities from shim bootstrap
A shim declared the mount types it performs itself through the annotation
removed in an earlier commit, discovered by invoking the shim binary a
second time with -info. Read them instead from the MountCapabilities
extension a shim advertises in its bootstrap result, which is already
available from the shim start that Create() performs anyway.

This requires starting the shim before activating the task's mounts.
Starting a shim does not need the rootfs; only the task.Create call
consumes it. Reordering means a failure after the shim has started must
now tear the shim down, so the teardown that was inlined in the
task.Create error path becomes a deferred cleanup covering the whole
window, reusing the existing cleanupShimTask helper. That defer is
registered after the mount deactivation defer so that the shim, which
may still be using the mounts, is stopped first.

Extract the mount activation logic into a new taskMountController in
task_mounts.go, rather than growing it further inline in Create(): it
already has its own state transitions (owned vs. reused activation,
NotImplemented, AlreadyExists) independent of shim startup, and this
keeps that reasoning testable without spawning a shim.

Also fix two latent nil pointer dereferences: Create() and Delete() both
called the mount.Manager interface directly with no nil check, which
panics whenever the mount manager plugin is not registered.
taskMountController.Activate and Deactivate treat a nil manager as
nothing to do.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan 6d9307f346 runtime/v2: decode the whole bootstrap result from JSON
parseStartResponse decodes a JSON bootstrap response into the deprecated
three-field client.BootstrapParams, so every other field of BootstrapResult
is silently discarded.

This is reached when reloading a bundle: writeBootstrapParams stores
bootstrap.json with encoding/json, and readBootstrapParams parses it back
through here. It matters once BootstrapResult carries extensions, because a
container joining an existing sandbox shim recovers that shim's result from
bootstrap.json rather than from a fresh shim start, and so would have seen
none of them.

Decode into BootstrapResult instead. The stored format does not change and
neither reader nor writer changes what it produces; encoding/json already
round-trips every field, including extensions, whose Any is an opaque type
URL and byte slice to it and so needs no type resolution, and including a
capability value this version of containerd does not define, which must
survive rather than being silently dropped.

This also removes the last use of the deprecated client.BootstrapParams.

Also fix TestRestoreBootstrapParams, which compared protobuf messages with
reflect-based deep equality. That is not sound, as generated types carry
internal state that varies with how the message was built.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:49:00 -07:00
Derek McGowan 329998caa9 runtime/v2: remove the runtime-allow-mounts annotation
A shim declared the mount types it performs itself through a comma
separated string in the generic annotations map of its RuntimeInfo,
discovered by invoking the shim binary a second time with -info. The
values had to reproduce by hand the "<transform>/*" sentinel the mount
manager constructs internally, there was nowhere to put anything but a
name, and it was keyed by runtime name rather than shim instance, so it
could not reflect anything about the environment a particular shim is
running in.

Remove it along with loadShimInfo, shimInfo and the shimInfos cache,
and the runc.v2/runhcs.v1 shortcut that only existed to avoid paying
for it on the default runtimes. This is a breaking change targeted at
2.4; known usage is limited to Nerdbox, which can adopt the shim
capability protocol added in the following commits after this merges.

getRuntimeInfo itself stays: it is also used by PluginInfo and
validateRuntimeFeatures.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-26 10:47:43 -07:00
ningmingxiao 452b4d99cc fix: fix incorrect restart=always restart logic
Signed-off-by: ningmingxiao <ning.mingxiao@zte.com.cn>
2026-08-21 12:51:24 +08:00
Maksym Pavlenko 55c39f2516 Move shim.Command to runtime
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-08-19 13:20:33 -07:00
Wei Fu 402eb3166e runtime: invoke Shutdown after every task deletion
TaskService.Shutdown may be invoked multiple times. A grouped shim
itself does not terminate while it still has active tasks. It terminates only
after receiving a Shutdown request when no active tasks remain.

The shim manager should invoke TaskService.Shutdown after deleting every task,
regardless of whether the task represents sandbox or not. This ensures that the
shim receives Shutdown when the last active task is deleted.

In CRI, the pause container uses oom_score_adj=-998, making it unlikely to be
OOM-killed. However, it may still exit or be killed before the other containers
in the sandbox. SandboxService.Shutdown and TaskService.Shutdown are independent
APIs. Sandbox service should make sure there is no active containers
before shutdown. So, for the task service, we should invoke Shutdown for
each task.

Removing the supportSandboxAPIVersion check does not change behavior for shims
using task API versions below v3. Those shims were already forced down the
non-sandboxed path and received Shutdown after every task deletion. The behavior
change applies only to sandboxed tasks using task API v3, which now receive
Shutdown after deletion as well.

Signed-off-by: Wei Fu <fuweid89@gmail.com>
2026-08-17 18:09:54 -04:00
Austin VazquezandHarshal Patel fd29ff1073 fix(runtime): bound shim loading with the load timeout
loadShim runs during runtime plugin initialization and issued its task
RPCs on the caller's context, which carries no deadline. A shim that
still owns its socket but has stopped serving, for example one leaked by
a previous containerd whose shutdown timed out, accepts the connection
and then never answers. containerd then never finishes starting and its
API socket is never created.

Give loadShim a single loadTimeout budget covering the whole load. Nested
timeouts can only shorten a deadline, so the load stays bounded however
many calls it makes.

Reaping a shim we give up on runs on its own cleanup budget, detached
from the caller so that a cancelled load cannot leave the shim behind. A
failed delete returns before shutting the shim down and closing its
client, so both are done here, and the failure is now propagated: delete
removes the bundle only when it succeeds, and returning an error lets
loadShims remove it, so a shim that cannot be reaped is no longer
reloaded on every subsequent start.

Co-authored-by: Harshal Patel <106813066+HarshalPatel1972@users.noreply.github.com>
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
2026-08-13 16:49:43 -05:00
Derek McGowan 29058e6501 Add more context to the shim delete error
When a shim delete hits a timeout, currently the error message does not
indicate that the delete was killed rather than failed to complete.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-08-06 17:19:05 -07:00
Paweł Gronowski 9c6b71c95c core/runtime/v2: Drop checkpointctl module dependency
The shim imported github.com/checkpoint-restore/checkpointctl/lib for a
single string constant.
Consumers that embed only the runtime v2 plugin (and never touch
internal/cri) therefore had to vendor the checkpointctl package.

Declare the file name as a local constant instead.
checkpointctl still remains a direct requirement here because
internal/cri/server uses its types, JSON readers, and annotations, but
it is no longer reachable from the runtime v2 import graph.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-24 20:33:58 +02:00
Maksym Pavlenko 4c9842f35e Merge pull request #13790 from halaney/ahalaney/shim-leak-error
shim_load: Consider shim leaked only if we can't find pids
2026-07-22 16:48:07 +00:00
Andrew Halaney 54a5a606cb shim_load: Consider shim leaked only if we can't find pids
Right now the statement is treating any error from the shim as leaking
(len(pInfo == 0 is true for any error). It seems the intent was to only
treat shims this way if the error was not found, or if there's
legitimately no pids associated with the shim. Let's fix that up to
avoid orphaning shims that just had a small error in reading pids.

Link: https://github.com/containerd/containerd/issues/13784
Signed-off-by: Andrew Halaney <ahalaney@netflix.com>
2026-07-20 13:38:01 -05:00
Paweł Gronowski dac4ea43f3 core/runtime/v2: Preserve protobuf shim response bytes
Shim start output was trimmed before protobuf decoding.
Because arbitrary protobuf fields may legitimately end with whitespace
bytes, including `\n`, trimming could corrupt metadata or capabilities
and cause decoding to fail.

Pass the raw command output to `parseStartResponse` and attempt protobuf
decoding before modifying the response.
Whitespace trimming now applies only to legacy JSON and plain-address
responses.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-16 19:03:21 +02:00
Samuel Karp 186397511b cri: validate CRIU availability and version early
Perform an early validation check on both container checkpoint and
restore paths to fail-fast if the CRIU binary is missing or is older
than the minimum required version (3.16.0).

To support runtime-configured environments, the validation respects the
custom PATH from the shim manager environment if configured, skipping
any relative paths to avoid incorrect daemon-relative resolution. If not
configured, it falls back to a standard system PATH lookup. The check
result is cached using sync.Once to prevent redundant process spawning.

Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
2026-06-30 12:35:16 -07:00
Austin Vazquez 88af11e081 core/runtime/v2: fix race on Windows deferredPipeConnection.c in Read
Read short-circuited on `if dpc.c == nil` before calling
`dpc.wg.Wait()` which races with the dialer goroutine spawned in
openShimLog. The dialer assigns `dpc.c = c` (and may set `dpc.conerr`)
outside any lock; the only synchronization is the WaitGroup, and Read
skipped it on the fast path.

Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
2026-05-21 17:15:58 -05:00
Maksym Pavlenko 3e0ebf0f6d Deprecate shim.Command
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-29 10:51:55 -07:00
Samuel Karp f7150e2215 Merge pull request #13126 from dmcgowan/handle-mount-already-exists
Fix mount manager activation error when already exists
2026-04-24 16:16:40 +00:00
Davanum Srinivas c30f23452c cri: use upstream Kubernetes modules
Switch the CRI integration layer from containerd's forked Kubernetes helpers
and clients to the upstream Kubernetes modules, and finalize the dependency
update to Kubernetes v0.36.0.

Replace the remaining internal helper copies with upstream packages:
- internal/cri/clock -> k8s.io/utils/clock
- internal/cri/executil -> upstream CRI exec helpers
- internal/cri/resourcequantity -> k8s.io/apimachinery/pkg/api/resource
- internal/cri/setutils -> k8s.io/apimachinery/pkg/util/sets
- internal/cri/types/labels.go -> internal/cri/labels
- integration/cri-api/pkg/apis/services.go -> k8s.io/cri-api/pkg/apis/services.go

Adopt the upstream CRI clients directly:
- add k8s.io/cri-client v0.36.0, k8s.io/cri-streaming v0.36.0, and
  k8s.io/streaming v0.36.0 as direct dependencies
- promote k8s.io/utils to a direct dependency and pull in
  k8s.io/component-base v0.36.0 indirectly
- keep integration/remote as a thin containerd adapter around cri-client,
  because the integration tests still need the stream-shaped
  GetContainerEvents RPC

Finalize the Kubernetes dependency update from v0.36.0-rc.0 to v0.36.0,
refresh vendor/, and drop the obsolete internal utility copies.

Also fix the protobuf MessageState mutex-copy vet failures exposed by the new
APIs and close the temporary integration CRI clients explicitly.

Signed-off-by: Davanum Srinivas <davanum@gmail.com>
2026-04-23 12:59:58 +02:00
Derek McGowan 80ec03fe7e core/mount: Fix mount manager activation error when already exists
Correctly handle cases where the mount activation still exists:
- If activation is fully activate, then just return already exists and
  allow the caller to return error or call Info to continue.
- If activation is stale or incomplete due to crash during activation,
  overwrite the identifier and cleanup the incomplete activation during
  activate.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-04-20 18:04:16 -07:00
Derek McGowan e07a1aa491 Add configuration for socket directory to the shim manager
Allow the socket directory to be directly configured by the shim manager
with reasonable defaults when not set. The default for root users will
still be the same directory under the default state directory. For
non-root users a temp directory will be used as default if the state
directory is not owned by the user.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-04-15 00:21:29 -07:00
Derek McGowan d806373feb Make shim socket directory use configured state
Send the socket directory from containerd to the shim. The shim still
decides where the socket goes but can use the environment variable
passed from containerd to ensure the socket is placed in the configured
directory with proper permission.

This is needed for some rootless cases which do not have permission to
the default state directory as currently set. The directory being
hardcoded by the shim means it is currently not possible to change the
location the shim will listen at.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-04-15 00:21:18 -07:00
Esteban Ginez 01e5fa616f fix: address review feedback on awaitPipeReady
- Use time.NewTimer + Stop() instead of time.After to avoid timer leaks
- Treat context.DeadlineExceeded as retryable (pipe busy, not just missing)
- Wrap last dial error instead of os.ErrNotExist for better diagnostics
- Update makeConnection godoc to reflect current BootstrapResult type

Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
2026-04-09 15:15:32 -07:00
Esteban Ginez 1e98ebaf0e fix(windows): verify pipe readiness before returning shim address
The shim "start" helper returns the named pipe address before the
daemon process has created the pipe via winio.ListenPipe(). On busy
Windows systems, containerd may try to connect before the pipe exists.

Add awaitPipeReady() — the start helper now polls the pipe address
(up to 5s, 10ms intervals) before writing the bootstrap result to
stdout. This follows hcsshim's readiness pattern where the shim
verifies its endpoint is ready before signaling the parent.

As a safety net, also parameterize makeConnection() with a dialer so
binary.Start() uses AnonDialer (retry) for new shims while loadShim()
keeps AnonReconnectDialer (fail-fast) for reconnects per #3659.

On Unix, awaitPipeReady() is a no-op: domain sockets appear atomically.

Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
2026-04-09 15:07:06 -07:00
Maksym Pavlenko 3c0e8a55b6 Update comments wording about when to deprecate and remove the old path
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Maksym Pavlenko 9dc864fd0f Switch to proto instead of json
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Derek McGowan 243cab594e Deprecate old pkg/shim interfaces
Signed-off-by: Derek McGowan <derek@mcg.dev>
2026-04-08 08:29:28 -05:00
Maksym Pavlenko d957b1bf53 Use log level instead of debug flag
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Maksym Pavlenko fa02acee20 Generate shim CLI flags under Command
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Maksym Pavlenko fc8062f379 Rename CommandConfig field to better reflect their purpose
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Maksym Pavlenko 7f39b2d933 Update shim to support new bootstrap api
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-08 08:29:28 -05:00
Jintao Zhang 22e6e1541c Add binary-v2 logging readiness scheme
Expose log URI schemes in runtime v2 metadata

Signed-off-by: Jintao Zhang <zhangjintao9020@gmail.com>
2026-04-05 13:41:15 +00:00
Maksym Pavlenko 169e000389 Move runtime v2 docs to ./docs
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-04-04 14:10:29 -07:00
Fletcher Woodruff b32cecd318 fix: handle nil spec for hostNetwork containers
When running hostNetwork containers with the shim sandboxer, the spec
passed to NewBundle is never initialized to a typed nil and is instead a
bare golang nil. Fix this by guarding the dereference to avoid crashing
when such a container is created.

Signed-off-by: Fletcher Woodruff <fwood@amazon.com>
2026-03-26 20:06:00 +00:00
Sebastiaan van Stijn 9bdcacc45f *: modernize: waitgroup
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-17 13:36:17 +01:00
Sebastiaan van Stijn 92b0b289e3 core: modernize: any
go install golang.org/x/tools/go/analysis/passes/modernize/cmd/modernize@latest
    modernize -any -fix ./...

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-15 18:24:14 +01:00
Fu Wei 591de24057 Merge pull request #12821 from haytok/propagate-deadline-exceeded-error
fix: propagate `context deadline exceeded` error properly
2026-02-21 21:58:31 +00:00
Hayato Kiwata f078cebbd1 fix: propagate context deadline exceeded error properly
When a shim becomes unresponsive (e.g., stopped via SIGSTOP), ttrpc
communication times out with `context deadline exceeded`.

Currently, this error is not properly propagated, causing redundant API
calls and slow container listing by client sides.

Specifically, when executing the API to check the task state, it appears
that the `context deadline exceeded` error via ttrpc is not being handled
within `shimTask.State()` and `getProcessState()`.

As a result, when this error occurs, clients such as nerdctl cannot
recognize this error, and it is thought that the issue described below is
occurring:

- https://github.com/containerd/nerdctl/issues/4720

Therefore, this commit adds error handling to ensure timeouts are properly
handled by client sides.

Signed-off-by: Hayato Kiwata <dev@haytok.jp>
2026-01-26 22:58:28 +09:00
Maksym Pavlenko 992597bfe9 Fix TTRPC prefix
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-01-15 13:06:50 -08:00
Maksym Pavlenko 253fbe756a Cleanup unit tests
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
2026-01-06 10:52:49 -08:00
Kal 5b184601d3 Fix typo in README.md for shim author section
Signed-off-by: Kal <119035751+Kaleab-Ayenew@users.noreply.github.com>
2025-12-16 15:20:25 +03:00