Skip to content

Commit fa457e6

Browse files
authored
WCOW: restore support for client-mounted roots (#2595)
Commit 00ca088 broke starting process-isolated containers when Root.Path is set in the container spec. Root.Path is set by clients such as Docker which mount and unmount the container's root filesystem themselves. Mounting is skipped, which also skips over setting coi.mountedWCOWLayers. The hcsoci.createWindowsContainerDocument function unconditionally dereferences that field, resulting in a nil-dereference panic when mounting is skipped. Restore the old behaviour by synthesizing the MountedWCOWLayers when Root.Path is set. Signed-off-by: Cory Snider <[email protected]>
1 parent 18193a4 commit fa457e6

2 files changed

Lines changed: 58 additions & 12 deletions

File tree

internal/hcsoci/resources_wcow.go

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,18 +34,26 @@ func allocateWindowsResources(ctx context.Context, coi *createOptionsInternal, r
3434
coi.Spec.Root = &specs.Root{}
3535
}
3636

37-
if coi.Spec.Root.Path == "" && (coi.HostingSystem != nil || coi.Spec.Windows.HyperV == nil) {
38-
log.G(ctx).Debug("hcsshim::allocateWindowsResources mounting storage")
39-
mountedLayers, closer, err := layers.MountWCOWLayers(ctx, coi.actualID, coi.HostingSystem, coi.WCOWLayers)
40-
if err != nil {
41-
return errors.Wrap(err, "failed to mount container storage")
42-
}
43-
coi.Spec.Root.Path = mountedLayers.RootFS
44-
coi.mountedWCOWLayers = mountedLayers
45-
// If this is the pause container in a hypervisor-isolated pod, we can skip cleanup of
46-
// layers, as that happens automatically when the UVM is terminated.
47-
if !isSandbox || coi.HostingSystem == nil {
48-
r.SetLayers(closer)
37+
if coi.HostingSystem != nil || coi.Spec.Windows.HyperV == nil {
38+
if coi.Spec.Root.Path == "" {
39+
log.G(ctx).Debug("hcsshim::allocateWindowsResources mounting storage")
40+
mountedLayers, closer, err := layers.MountWCOWLayers(ctx, coi.actualID, coi.HostingSystem, coi.WCOWLayers)
41+
if err != nil {
42+
return errors.Wrap(err, "failed to mount container storage")
43+
}
44+
coi.Spec.Root.Path = mountedLayers.RootFS
45+
coi.mountedWCOWLayers = mountedLayers
46+
// If this is the pause container in a hypervisor-isolated pod, we can skip cleanup of
47+
// layers, as that happens automatically when the UVM is terminated.
48+
if !isSandbox || coi.HostingSystem == nil {
49+
r.SetLayers(closer)
50+
}
51+
} else {
52+
l, err := layers.MakeMountedWCOWLayers(ctx, coi.WCOWLayers, coi.Spec.Root.Path)
53+
if err != nil {
54+
return errors.Wrap(err, "failed to use pre-mounted container storage")
55+
}
56+
coi.mountedWCOWLayers = l
4957
}
5058
}
5159

internal/layers/wcow_mount.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,44 @@ func MountWCOWLayers(ctx context.Context, containerID string, vm *uvm.UtilityVM,
4949
}
5050
}
5151

52+
// MakeMountedWCOWLayers creates a MountedWCOWLayers structure from wl, like
53+
// [MountWCOWLayers], without actually mounting anything.
54+
func MakeMountedWCOWLayers(ctx context.Context, wl WCOWLayers, mountPath string) (*MountedWCOWLayers, error) {
55+
switch l := wl.(type) {
56+
case *wcowWCIFSLayers:
57+
layersWithID := []MountedWCOWLayer{}
58+
for _, l := range l.layerPaths {
59+
layerID, err := wclayer.LayerID(ctx, l)
60+
if err != nil {
61+
return nil, err
62+
}
63+
layersWithID = append(layersWithID, MountedWCOWLayer{
64+
LayerID: layerID.String(),
65+
MountedPath: l,
66+
})
67+
}
68+
69+
return &MountedWCOWLayers{
70+
RootFS: mountPath,
71+
MountedLayerPaths: layersWithID,
72+
}, nil
73+
case *wcowForkedCIMLayers, *wcowBlockCIMLayers:
74+
layerID, err := cimlayer.LayerID(mountPath)
75+
if err != nil {
76+
return nil, err
77+
}
78+
return &MountedWCOWLayers{
79+
RootFS: mountPath,
80+
MountedLayerPaths: []MountedWCOWLayer{{
81+
LayerID: layerID,
82+
MountedPath: mountPath,
83+
}},
84+
}, nil
85+
default:
86+
return nil, fmt.Errorf("invalid layer type %T", wl)
87+
}
88+
}
89+
5290
// Represents a single layer that is mounted and ready to use. Depending on the type of
5391
// layers each individual layer may or may not be mounted. However, HCS still needs paths
5492
// of individual layers and a unique ID for each layer.

0 commit comments

Comments
 (0)