awaitPipeReady retried only when DialPipe returned os.IsNotExist or
context.DeadlineExceeded, but winio.DialPipe converts the per-attempt
deadline into winio.ErrTimeout before returning. A pipe in state 1
(ListenPipe called, Accept not yet called) causes DialPipe to block for
the full per-attempt timeout and return winio.ErrTimeout, which the old
check treated as a fatal error instead of retrying.
Also guard windows.ERROR_PIPE_BUSY explicitly to match the error checks
in containerd/nerdbox#218.
Adds a regression test that forces the state-1 to state-2 transition
race by delaying Accept past the 1-second per-attempt timeout.
Signed-off-by: Esteban Ginez <esteban.ginez@docker.com>
Image config labels are copied onto the container by both the CRI
plugin (BuildLabels) and the client's WithImageConfigLabels option
used by `ctr run`. Labels in the containerd.io/* namespace are
interpreted by containerd itself and labels in the io.cri-containerd*
namespace are interpreted by the CRI plugin. An image config is not a
trusted source for labels in either namespace.
Skip labels in both reserved namespaces when copying labels from an
image config to a container, and warn about each label skipped: an
image that tries to set them may be attempting to alter containerd
behavior. Oversized image labels are already skipped this way by
the CRI plugin.
Labels set explicitly by clients, for example via `ctr run --label`
or in the CRI request, are unaffected.
Verified with the CRI plugin and with `ctr run` against an image
whose config carries labels like these: the labels are no longer
present on the created container and a warning is logged for each.
Assisted-by: Claude Code
Signed-off-by: Ben Cressey <ben@cressey.org>
Signed-off-by: Samuel Karp <samuelkarp@google.com>
`strconv.NumError` implements `Unwrap` (see https://go.dev/cl/194563),
so there's no need to manually assert the type and unwrap.
Updates 9439355c2b
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
openUserFile now stats the opened file, refuses anything that is not a
regular file, and wraps the returned fs.File so reads are capped at
maxUserFileBytes (10 MiB). All callers of openUserFile read either
etc/passwd or etc/group; both are regular files on real systems, well
under the cap.
The cap and the regular-file check together bound parser memory use
when reading user-database files of unexpected shape or size.
Adds tests for the cap and for the non-regular file rejection. The cap
test covers three boundary points: a small pad (trailing entry parsed),
a pad placing the entry's last byte exactly on the cap (still parsed),
and a pad past the cap (read returns an "exceeds" error).
Assisted-by: Antigravity
Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
Commit f9c80be1b removed varcheck linter, but some nolint:varcheck
annotations are still there, resulting in golangci-lint warning:
> WARN [runner/nolint_filter] Found unknown linters in //nolint directives: varcheck
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
InitRootFS was added in #1477 for potential future use but has no
callers either inside or outside this repository. Remove it along
with the associated Mounter interface, initializerFunc type,
createInitLayer helper, and the platform-specific init files that
only existed to support it.
Fixes#13238
Signed-off-by: Sanil2108 <sanilkhurana7@gmail.com>
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>
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>
Avoid using logrus concepts in the API, use slog style log levels with
integer values and 0 meaning the default "info" level.
Signed-off-by: Derek McGowan <derek@mcg.dev>
- 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>
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>
Revert changes related to reading annotations in runc v2 shim,
because this requires a special path for runc shim. This complicates
migration to the new bootstrap API.
Signed-off-by: Maksym Pavlenko <pavlenko.maksym@gmail.com>
The `os.IsNotExist` documentation is clear that it should only be used to
check the error returned from calls within the os package, calls via
`fs.FS` should use `errors.Is`.
Signed-off-by: Derek McGowan <derek@mcg.dev>
Remove `runtime.GOOS == "darwin"` checks from WithUser,
WithAdditionalGIDs, and WithAppendAdditionalGroups. These guards
prevented supplementary group resolution when containerd runs on a
non-Linux host (e.g. macOS or Windows) that creates Linux containers.
The `s.Windows != nil` check for LCOW is retained.
Move user/group tests from spec_opts_linux_test.go to the new
cross-platform spec_opts_user_test.go so they run on all platforms.
Signed-off-by: Rob Murray <rob.murray@docker.com>
Introduce functional options to NewLogrusHook to allow optional Trace ID
injection into log fields. This enables log-trace correlation via the
[debug] config without breaking existing external consumers of
pkg/tracing.
Signed-off-by: Hasan Siddiqui <hasiddiqui@google.com>
The `go-cmp` library has issues with Go deadcode elimination:
```
github.com/google/go-cmp/cmp/internal/value.appendTypeName reachable from:
github.com/google/go-cmp/cmp.pathStep.String
type:github.com/google/go-cmp/cmp.pathStep
type:github.com/google/go-cmp/cmp.structField
type:*github.com/google/go-cmp/cmp.structField
type:github.com/google/go-cmp/cmp.StructField
go:itab.github.com/google/go-cmp/cmp.StructField,github.com/google/go-cmp/cmp.PathStep
github.com/google/go-cmp/cmp.Path.String
type:github.com/google/go-cmp/cmp.Path
type:github.com/google/go-cmp/cmp.state
type:*github.com/google/go-cmp/cmp.state
type:func(*github.com/google/go-cmp/cmp.state, reflect.Type, reflect.Value, reflect.Value) github.com/google/go-cmp/cmp.applicableOption
type:github.com/google/go-cmp/cmp.Option
github.com/google/go-cmp/cmp.flattenOptions
github.com/google/go-cmp/cmp.normalizeOption
github.com/google/go-cmp/cmp.FilterValues
github.com/containerd/containerd/v2/pkg/protobuf.init
github.com/containerd/containerd/v2/pkg/protobuf..inittask
go:main.inittasks
```
The `pkg/protobuf` is imported unconditionally is
`github.com/containerd/containerd` Go module is imported via init tasks,
so there is no way e.g. to use containerd client without triggering this
import.
It seems that within containerd itself this function is only used from
tests, so hiding it this way allows to import `containerd/client` while
keeping deadcode elimination.
Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com>
newFakeImage used digest.NewDigestFromBytes which hex-encodes the raw
bytes rather than hashing them, producing a digest with an invalid
length. This was previously harmless since the embedded data path in
content.ReadBlob never matched, but now that the digest is validated
before use, the invalid digest causes an error.
Use digest.Canonical.FromBytes which correctly hashes the content.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>