From 64cda91f855dc00dbbb24daa1ac36ec349af96fa Mon Sep 17 00:00:00 2001 From: Martin Harriman Date: Thu, 27 Jun 2024 22:28:22 +0000 Subject: [PATCH] Fix segfault in host-ctr Bottlerocket invokes the host-ctr executable with an optional "--registry-config" parameter. If this parameter was omitted (for instance, in customer code), host-ctr would segfault. Now it will behave as it would for an empty registry-config file. --- sources/host-ctr/cmd/host-ctr/main.go | 11 ++++++++--- sources/host-ctr/cmd/host-ctr/registry.go | 19 +++++++++++++++---- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/sources/host-ctr/cmd/host-ctr/main.go b/sources/host-ctr/cmd/host-ctr/main.go index 704d87a45..2f51cd296 100644 --- a/sources/host-ctr/cmd/host-ctr/main.go +++ b/sources/host-ctr/cmd/host-ctr/main.go @@ -1033,6 +1033,8 @@ func pullImage(ctx context.Context, source string, client *containerd.Client, re Error("failed to read registry config") return nil, err } + } else { + registryConfig = NewBlankRegistryConfig() } // Pull the image @@ -1152,9 +1154,12 @@ func withDynamicResolver(ctx context.Context, ref string, registryConfig *Regist } // For Amazon ECR Public registries, we should try and fetch credentials before resolving the image reference case strings.HasPrefix(ref, "public.ecr.aws/"): - // ... not if the user has specified their own registry credentials for 'public.ecr.aws'; In that case we use the default resolver. - if _, found := registryConfig.Credentials["public.ecr.aws"]; found { - return defaultResolver + // if we have registryConfig, and the user specified credentials for + // 'public.ecr.aws', then use defaultResolver. + if registryConfig != nil { + if _, found := registryConfig.Credentials["public.ecr.aws"]; found { + return defaultResolver + } } // Try to get credentials for authenticated pulls from ECR Public diff --git a/sources/host-ctr/cmd/host-ctr/registry.go b/sources/host-ctr/cmd/host-ctr/registry.go index 9a79ae946..5e628ed66 100644 --- a/sources/host-ctr/cmd/host-ctr/registry.go +++ b/sources/host-ctr/cmd/host-ctr/registry.go @@ -45,6 +45,13 @@ func NewRegistryConfig(registryConfigFile string) (*RegistryConfig, error) { return &config, toml.Unmarshal(raw, &config) } +// NewBlankRegistryConfig sets up a RegistryConfig without unmarshalling any toml +func NewBlankRegistryConfig() *RegistryConfig { + config := RegistryConfig{} + // no config to unmarshal + return &config +} + // registryHosts returns the registry hosts to be used by the resolver. // Heavily borrowed from containerd CRI plugin's implementation. // See https://github.com/containerd/containerd/blob/1407cab509ff0d96baa4f0eb6ff9980270e6e620/pkg/cri/server/image_pull.go#L332-L405 @@ -58,15 +65,19 @@ func registryHosts(registryConfig *RegistryConfig, authorizerOverride *docker.Au authConfig runtime.AuthConfig ) // Set up endpoints for the registry - if _, ok := registryConfig.Mirrors[host]; ok { - endpoints = registryConfig.Mirrors[host].Endpoints - } else { - endpoints = registryConfig.Mirrors["*"].Endpoints + // The endpoints array may still be empty after this step + if registryConfig != nil { + if _, ok := registryConfig.Mirrors[host]; ok { + endpoints = registryConfig.Mirrors[host].Endpoints + } else if _, ok := registryConfig.Mirrors["*"]; ok { + endpoints = registryConfig.Mirrors["*"].Endpoints + } } defaultHost, err := docker.DefaultHost(host) if err != nil { return nil, errors.Wrap(err, "get default host") } + // append this default host to the possibly-empty endpoints array endpoints = append(endpoints, defaultHost) for _, endpoint := range endpoints {