Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions internal/gcs-sidecar/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package bridge

import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -130,6 +131,15 @@ func (b *Bridge) createContainer(req *request) (err error) {
return fmt.Errorf("CreateContainer operation is denied by policy: %w", err)
}

// Create the source directory for each mapped directory if it does not
// already exist. In non-confidential WCOW the host does this for
// sandbox:// mounts by exec'ing `cmd /c mkdir ... & dir ...` inside the
// UVM (see resources_wcow.go:setupMounts), but for confidential, we
// handle this here in the sidecar GCS.
if err := createMappedDirectorySourceDirs(ctx, container.MappedDirectories); err != nil {
return fmt.Errorf("failed to create mapped directory source directories: %w", err)
}
Comment on lines +139 to +141

commandLine := len(spec.Process.Args) > 0
c := &Container{
id: containerID,
Expand Down Expand Up @@ -201,6 +211,28 @@ func (b *Bridge) createContainer(req *request) (err error) {
return nil
}

// createMappedDirectorySourceDirs creates the host-side source directory for
// every mapped directory (i.e. "mounts") in the container document, if it does
// not already exist.
func createMappedDirectorySourceDirs(ctx context.Context, mappedDirectories []hcsschema.MappedDirectory) error {
for _, md := range mappedDirectories {
source := md.HostPath

if _, err := os.Stat(source); err == nil {
// exists
continue
} else if !os.IsNotExist(err) {
return fmt.Errorf("failed to stat mapped directory source %q: %w", source, err)
}

if err := os.MkdirAll(source, 0755); err != nil {
return fmt.Errorf("failed to create mapped directory source %q: %w", source, err)
}
log.G(ctx).WithField("source", source).Debug("created mapped directory source directory")
}
return nil
}

// processParamEnvToOCIEnv converts an Environment field from ProcessParameters
// (a map from environment variable to value) into an array of environment
// variable assignments (where each is in the form "<variable>=<value>") which
Expand Down
35 changes: 21 additions & 14 deletions internal/hcsoci/resources_wcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,27 @@ func setupMounts(ctx context.Context, coi *createOptionsInternal, r *resources.R
// Now we need to exec a process in the vm that will make these directories as theres
// no functionality in the Windows gcs to create an arbitrary directory.
//
// Create the directory, but also run dir afterwards regardless of if mkdir succeeded to handle the case where the directory already exists
// e.g. from a previous container specifying the same mount (and thus creating the same directory).
b := &bytes.Buffer{}
stderr, err := cmd.CreatePipeAndListen(b, false)
if err != nil {
return err
}
req := &cmd.CmdProcessRequest{
Args: []string{"cmd", "/c", "mkdir", sandboxPath, "&", "dir", sandboxPath},
Stderr: stderr,
}
exitCode, err := coi.HostingSystem.ExecInUVM(ctx, req)
if err != nil {
return errors.Wrapf(err, "failed to create sandbox mount directory in utility VM with exit code %d %q", exitCode, b.String())
// We do not need to do this for Confidential WCOW, because in that case the gcs-sidecar
// handles the create container request and will do this for us. This way the policy
// does not have to have exceptions for allowing such mkdir commands.
//
// Create the directory, but also run dir afterwards regardless of if mkdir succeeded to
// handle the case where the directory already exists e.g. from a previous container
// specifying the same mount (and thus creating the same directory).
if !coi.HostingSystem.HasConfidentialPolicy() {
b := &bytes.Buffer{}
stderr, err := cmd.CreatePipeAndListen(b, false)
if err != nil {
return err
}
req := &cmd.CmdProcessRequest{
Args: []string{"cmd", "/c", "mkdir", sandboxPath, "&", "dir", sandboxPath},
Stderr: stderr,
}
exitCode, err := coi.HostingSystem.ExecInUVM(ctx, req)
if err != nil {
return errors.Wrapf(err, "failed to create sandbox mount directory in utility VM with exit code %d %q", exitCode, b.String())
}
}
} else if np, ok := uvm.ParseNamedPipe(coi.HostingSystem, mount); ok {
if !np.UVMPipe {
Expand Down
Loading