|
5 | 5 | "fmt" |
6 | 6 | "os" |
7 | 7 | "runtime" |
8 | | - "runtime/debug" |
9 | 8 | "strings" |
10 | 9 |
|
11 | 10 | "github.com/google/go-containerregistry/pkg/authn" |
@@ -318,6 +317,14 @@ func (c *ociClient) unpackLayers(ctx context.Context, layoutTag, targetDir strin |
318 | 317 | return fmt.Errorf("get manifest: %w", err) |
319 | 318 | } |
320 | 319 |
|
| 320 | + configFile, err := img.ConfigFile() |
| 321 | + if err != nil { |
| 322 | + return fmt.Errorf("get config file: %w", err) |
| 323 | + } |
| 324 | + if err := validateConfigFileForUnpack(layoutTag, gcrManifest, configFile); err != nil { |
| 325 | + return err |
| 326 | + } |
| 327 | + |
321 | 328 | // Convert go-containerregistry manifest to OCI v1.Manifest for umoci |
322 | 329 | ociManifest := convertToOCIManifest(gcrManifest) |
323 | 330 |
|
@@ -352,26 +359,36 @@ func (c *ociClient) unpackLayers(ctx context.Context, layoutTag, targetDir strin |
352 | 359 | }, |
353 | 360 | } |
354 | 361 |
|
355 | | - var panicErr error |
356 | | - func() { |
357 | | - defer func() { |
358 | | - if r := recover(); r != nil { |
359 | | - panicErr = fmt.Errorf("panic in unpack rootfs for %s: %v\n%s", layoutTag, r, debug.Stack()) |
360 | | - } |
361 | | - }() |
362 | | - |
363 | | - err = layer.UnpackRootfs(ctx, casEngine, targetDir, ociManifest, unpackOpts) |
364 | | - }() |
365 | | - if panicErr != nil { |
366 | | - return panicErr |
367 | | - } |
| 362 | + err = layer.UnpackRootfs(ctx, casEngine, targetDir, ociManifest, unpackOpts) |
368 | 363 | if err != nil { |
369 | 364 | return fmt.Errorf("unpack rootfs: %w", err) |
370 | 365 | } |
371 | 366 |
|
372 | 367 | return nil |
373 | 368 | } |
374 | 369 |
|
| 370 | +func validateConfigFileForUnpack(layoutTag string, manifest *gcr.Manifest, configFile *gcr.ConfigFile) error { |
| 371 | + if convertToOCIMediaType(string(manifest.Config.MediaType)) != v1.MediaTypeImageConfig { |
| 372 | + return fmt.Errorf( |
| 373 | + "unpack rootfs: config blob is not correct mediatype %s: %s", |
| 374 | + v1.MediaTypeImageConfig, |
| 375 | + manifest.Config.MediaType, |
| 376 | + ) |
| 377 | + } |
| 378 | + if configFile.RootFS.Type != "layers" { |
| 379 | + return fmt.Errorf("unpack rootfs: config: unsupported rootfs.type: %s", configFile.RootFS.Type) |
| 380 | + } |
| 381 | + if len(configFile.RootFS.DiffIDs) != len(manifest.Layers) { |
| 382 | + return fmt.Errorf( |
| 383 | + "unpack rootfs: config rootfs.diff_ids has %d entries but manifest has %d layers for %s", |
| 384 | + len(configFile.RootFS.DiffIDs), |
| 385 | + len(manifest.Layers), |
| 386 | + layoutTag, |
| 387 | + ) |
| 388 | + } |
| 389 | + return nil |
| 390 | +} |
| 391 | + |
375 | 392 | // convertToOCIManifest converts a go-containerregistry manifest to OCI v1.Manifest |
376 | 393 | // This allows us to use go-containerregistry (which handles both Docker v2 and OCI v1) |
377 | 394 | // for manifest parsing, while still using umoci for layer unpacking. |
|
0 commit comments