On a terminal process, a single PTY master file descriptor carries both
stdin and stdout/stderr. The stdin FIFO can reach EOF while the process
is still running, either when a client calls CloseIO to close stdin or
when an empty client stdin stream closes before openStdin's background
writer opens in the kernel. Shutting down and closing the PTY master
when the stdin copy goroutine returns hangs up the terminal, which
sends SIGHUP to the process, causes writes to the slave to fail with
EIO, and causes stdout reads from the master to fail with EBADF.
Close only the stdin FIFO reader when the stdin copy goroutine finishes.
Closing stdin via CloseIO on a terminal process leaves the PTY master
open and the process running without sending SIGHUP.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
pullProgressReporter samples activeReqs and totalBytesRead on a periodic
ticker. A response with an empty body, such as a manifest Resolve HEAD
request, does not increment totalBytesRead. In addition, an activeReqs
transition to zero and back to one between ticker ticks is not observed
by the ticker. In both cases, lastSeenTimestamp is not updated and a
subsequent request can be cancelled before it has run for timeout.
Record the timestamp of the most recent request start, response header
receipt, or body byte read in pullRequestReporter, and advance
lastSeenTimestamp from that timestamp on each tick.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Exclude the core/runtime/v2/README.md symlink in the links workflow so
lychee does not fail resolving relative links from the symlink path.
docs/runtime-v2.md is already validated directly.
Update broken, moved, and rate-limited links across markdown documents:
- Replace moved Kubernetes cgroup driver and GCP registry docs.
- Replace retired RHEL 6 devmapper docs with kernel.org reference.
- Point NSSM, CRIU, and Ansible references to GitHub repositories.
- Fix relative paths in remote-snapshotter.md and root-relative paths.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Pin workflow runners to ubuntu-24.04 to avoid deprecation warnings and
breaking changes when ubuntu-latest migrates to Ubuntu 26.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
limactl start creates the default instance directory before downloading
the guest image. Delete the stopped instance before retrying so the
second limactl start invocation does not fail on an existing instance.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Stream chunks through a chunkReader backed by a channel of capacity
parallelism so at most parallelism pipes are allocated at any time.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
systemd-tmpfiles-clean.timer runs 15 minutes after boot and removes
empty directories under /tmp with mtimes older than 10 days. Some
integration tests place containerd's root in t.TempDir() and unpack
image layers with older directory timestamps under /tmp. If the timer
fires during extraction, systemd-tmpfiles removes newly created empty
directories before the final directory timestamp pass.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Reject negative sizes in content.Copy, remotes.Fetch,
dockerFetcher.Fetch, and newHTTPReadSeeker.
Bound reads in content.Copy and httpReadSeeker.Read to the remaining
expected size from the current offset, returning
errdefs.ErrFailedPrecondition if the source yields extra bytes.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Commit 192168038e removed the separate integration/client Go module
and merged its dependencies into the root module and vendor directory.
Running `go mod download` before `go test` in integration/client is
unnecessary because `go test` uses the root vendor directory.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Skip the linters steps when running in private repositories while
allowing the job itself to succeed so downstream jobs with
`needs: [..., linters, ...]` still run. Exclude macos-latest and
windows-latest from the linters matrix on private repositories to
avoid starting unnecessary runners.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Private forks of containerd are used for validating security patches
ahead of public disclosure. Some jobs should not run in that context.
Guard pull_request and push jobs with !github.event.repository.private
so they continue to run on containerd/containerd and public forks.
Because schedule events do not populate github.event.repository, guard
scheduled runs in nightly.yml and scorecards.yml with
github.repository == 'containerd/containerd'.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
urfave/cli/v3 breaks out of its flag parsing loop when it encounters a
"-" positional argument without appending the remaining arguments,
causing "ctr images export - <image>" to drop all image references and
flags following "-".
When <out> is "-", recover the un-truncated arguments from the parent
"images" command lineage and re-parse the tail starting at "-" with a
sentinel placeholder so trailing image references and flags are
preserved.
This workaround can be removed after the bug is fixed upstream:
* https://github.com/urfave/cli/issues/2418
* https://github.com/urfave/cli/pull/2419
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
"containerd oci-hook" defines no flags of its own and passes all
arguments directly to the target hook binary via syscall.Exec. Set
StopOnNthArg to 1 so urfave/cli/v3 stops flag parsing after the hook
binary path while still stripping an optional "--" separator.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
urfave/cli/v3 scans for flags across all positional arguments by
default, which causes flags meant for the container process to be
parsed as ctr flags.
Configure StopOnNthArg to stop flag parsing before the container
command and its arguments:
- "ctr run" and "ctr containers create": after Image|RootFS and
CONTAINER (2 args)
- "ctr tasks exec": after CONTAINER (1 arg)
Fixes#14208
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
In urfave/cli/v3, child commands do not inherit
DisableSliceFlagSeparator from the root command, unlike in
urfave/cli/v2. When containerd migrated to v3 in commit f72829f36,
subcommands inadvertently reverted to splitting slice flags on commas,
breaking flags that expect comma-separated values such as
--mount type=bind,src=/tmp,dst=/host,options=rbind:ro.
Explicitly set DisableSliceFlagSeparator on all cli.Command structs in
cmd/ctr/commands, restoring the behavior where slice flags are not
split on commas.
Fixes#14181
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Remove support for service_name and sampling_ratio in the
io.containerd.internal.v1.tracing plugin configuration, which was
previously deprecated in v1.6.29. Users should use standard OTel
environment variables instead (OTEL_SERVICE_NAME, OTEL_TRACES_SAMPLER,
etc.).
Re-add unit tests in pkg/tracing/plugin/otlp_test.go to verify
OTel environment variable configuration for service name, sampling,
exporters, and SDK disabling.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Add unit tests in pkg/tracing/plugin/otlp_test.go to verify newExporter,
checkDisabled, and newTracer with the OpenTelemetry environment
variables that replaced the deprecated OTLP plugin configuration fields.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Remove the deprecated endpoint, protocol, and insecure configuration
options for the io.containerd.tracing.processor.v1.otlp plugin.
These were deprecated in v1.6.29 and replaced by standard OTLP
environment variables.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
The `bin_dir` property of `[plugins."io.containerd.cri.v1.runtime".cni]`
was deprecated in containerd v2.1 in favor of `bin_dirs` and was
scheduled for removal in v2.4.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Remove the `enable_cdi` configuration option in
`[plugins."io.containerd.cri.v1.runtime"]`, which was deprecated in
v2.2. CDI support is now always enabled.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Delay the removal of the auths, configs, and mirrors properties in
[plugins."io.containerd.grpc.v1.cri".registry] until containerd 2.7.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
When unpacking a layer changeset in applyNaive, encountering an opaque
whiteout (.wh..wh..opq) triggers a directory walk to remove files
belonging to lower layers. Since files unpacked earlier in the current
layer are recorded in unpackedPaths and preserved, interleaved files and
opaque whiteouts in the same directory cause repeated walks over the
same growing directory, leading to superlinear execution time.
Once a directory has been purged of lower-layer files by an opaque
whiteout, all existing and subsequent entries in that directory are
guaranteed to be in unpackedPaths. Tracking directories that have
already processed an opaque whiteout allows subsequent opaque whiteouts
for the same directory to return early, restoring linear unpack time.
Benchmark results (n=1,000):
| Metric | Pre-change | Post-change | Delta |
| :--- | :--- | :--- | :--- |
| Execution Time | 2,578.8 ms/op | 135.3 ms/op | ~19.1x faster (94.8% reduction) |
| Allocated Memory | 200.5 MB/op | 2.3 MB/op | ~86.9x less memory (98.8% reduction) |
| Allocs / op | 2,068,820 allocs/op | 48,060 allocs/op | ~43.0x fewer allocs (97.7% reduction) |
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Add proof-of-concept (PoC) execution requirements against a running
daemon to the triage guide and threat model.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Remove support for restoring checkpoint data during CreateContainer,
which was previously deprecated in v2.3.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Exclude priority/*, status/accepted, status/needs-major-release, and
status/roadmapped labels from being marked as stale and closed.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Adds a new --scrub-logs flag to ctr run on Windows. This flag enables
the ScrubLogs option for the io.containerd.runhcs.v1 shim.
Assisted-by: gemini-cli
Signed-off-by: Samuel Karp <samuelkarp@google.com>
The io.containerd.runhcs.v1 shim can scrub sensitive information from
logs it emits. Since v0.15.0-rc.2 this is done by default, but older
branches still require the option to be explicitly enabled. Explicitly
enable the scrubbing by default for the CRI configuration.
See also: https://github.com/microsoft/hcsshim/pull/2725
Google-Bug-Id: 481375460
Signed-off-by: Samuel Karp <samuelkarp@google.com>
The debug server plugin returns ErrSkipPlugin when its address is empty
and the default configuration emitted by 'containerd config default'
sets the address to an empty string.
Assisted-by: Claude Code (Opus 4.8)
Signed-off-by: Samuel Karp <samuelkarp@google.com>
This commit introduces a comprehensive threat model, and security
triage guide, and operator guidelines based on the code, documentation
and a review of the published GitHub Security Advisories (GHSAs)
Assisted-by: gemini-cli
Assisted-by: Antigravity
Assisted-by: Claude Code (Opus 4.8)
Co-authored-by: Vinayak Goyal <vinayakankugoyal@gmail.com>
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Vagrant 2.4.x bundles an embedded Ruby 3.3.0 runtime that loads the
default specification json-2.7.2 during initialization. When installing
vagrant-libvirt, RubyGems resolves the newly released fog-json 1.4.0,
which requires json (~> 2.19). Because json-2.7.2 is already active in
memory when Vagrant starts up, RubyGems raises a Gem::ConflictError.
To avoid this conflict, pin fog-json to version 1.2.0 before installing
vagrant-libvirt. Since CI caches /root/.vagrant.d across runs, also
uninstall fog-json first to remove any conflicting version left in cache
by a previous job.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
The Kubernetes E2E CI workflow was failing on tests requiring container
checkpointing because criu was not installed on the GitHub Actions
runner.
Add a step to install criu via ppa:criu/ppa before building and
installing containerd, matching the existing setup in ci.yml.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
Add a new `enable_criu` configuration option under CRI plugin runtime
settings. When set to false, any checkpoint or restore request will fail
fast with an error indicating that CRIU support is disabled by
configuration. `enable_criu` currently defaults to true.
Add an integration test script to verify that setting `enable_criu` to
false in containerd configuration successfully disables checkpoint and
restore operations and fails fast.
Assisted-by: Antigravity
Signed-off-by: Samuel Karp <samuelkarp@google.com>
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>