Skip to content

Commit 085b2c3

Browse files
committed
WIP: Detect runc features based on RuntimeInfo
Signed-off-by: Rodrigo Campos <[email protected]>
1 parent c37ec33 commit 085b2c3

1 file changed

Lines changed: 58 additions & 0 deletions

File tree

runtime/v2/manager.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package v2
1919
import (
2020
"bytes"
2121
"context"
22+
"errors"
2223
"fmt"
2324
"os"
2425
"os/exec"
@@ -42,6 +43,9 @@ import (
4243
"github.com/containerd/containerd/runtime"
4344
shimbinary "github.com/containerd/containerd/runtime/v2/shim"
4445
"github.com/containerd/containerd/sandbox"
46+
"github.com/containerd/typeurl/v2"
47+
"github.com/opencontainers/runtime-spec/specs-go"
48+
"github.com/opencontainers/runtime-spec/specs-go/features"
4549
)
4650

4751
// Config for the v2 runtime
@@ -420,6 +424,10 @@ func (m *TaskManager) Create(ctx context.Context, taskID string, opts runtime.Cr
420424
return nil, err
421425
}
422426

427+
if err := m.validateRuntimeFeatures(ctx, opts); err != nil {
428+
return nil, fmt.Errorf("failed to validate OCI runtime features: %w", err)
429+
}
430+
423431
t, err := shimTask.Create(ctx, opts)
424432
if err != nil {
425433
// NOTE: ctx contains required namespace information.
@@ -532,3 +540,53 @@ func (m *TaskManager) RuntimeInfo(ctx context.Context, runtimeName string, runti
532540
}
533541
return &info, nil
534542
}
543+
544+
func (m *TaskManager) validateRuntimeFeatures(ctx context.Context, opts runtime.CreateOpts) error {
545+
// Get a typed version of the spec.
546+
var spec specs.Spec
547+
if err := typeurl.UnmarshalTo(opts.Spec, &spec); err != nil {
548+
return fmt.Errorf("unmarshal spec: %w", err)
549+
}
550+
551+
// Get features from runtime.
552+
rInfo, err := m.RuntimeInfo(ctx, opts.Runtime, nil)
553+
if err != nil {
554+
return fmt.Errorf("runtime info: %w", err)
555+
}
556+
557+
feat, err := typeurl.UnmarshalAny(rInfo.Features)
558+
if err != nil {
559+
return fmt.Errorf("unmarshal runtime features: %w", err)
560+
}
561+
features, ok := feat.(*features.Features)
562+
if !ok {
563+
return fmt.Errorf("invalid features type: %T", rInfo.Features)
564+
}
565+
566+
if err := validateIDMapMounts(spec, features); err != nil {
567+
return fmt.Errorf("idmap mounts: %w", err)
568+
}
569+
return nil
570+
}
571+
572+
func validateIDMapMounts(spec specs.Spec, features *features.Features) error {
573+
var idmapUsed bool
574+
for _, m := range spec.Mounts {
575+
if m.UIDMappings != nil || m.GIDMappings != nil {
576+
idmapUsed = true
577+
break
578+
}
579+
}
580+
if !idmapUsed {
581+
return nil
582+
}
583+
584+
if features.Linux.MountExtensions == nil || features.Linux.MountExtensions.IDMap == nil {
585+
return errors.New("missing `mountExtensions.idmap` entry in `features` command")
586+
587+
}
588+
if enabled := features.Linux.MountExtensions.IDMap.Enabled; enabled == nil || !*enabled {
589+
return errors.New("not supported or disabled")
590+
}
591+
return nil
592+
}

0 commit comments

Comments
 (0)