diff --git a/cmd/containerd-shim-runhcs-v1/pod.go b/cmd/containerd-shim-runhcs-v1/pod.go index 6a8f5ef62c..76b126b007 100644 --- a/cmd/containerd-shim-runhcs-v1/pod.go +++ b/cmd/containerd-shim-runhcs-v1/pod.go @@ -187,6 +187,7 @@ func createPod(ctx context.Context, events publisher, req *task.CreateTaskReques } case *uvm.OptionsWCOW: wopts := (opts).(*uvm.OptionsWCOW) + wopts.BundleDirectory = req.Bundle err = initializeWCOWBootFiles(ctx, wopts, req.Rootfs, s) if err != nil { return nil, err diff --git a/cmd/gcs-sidecar/main.go b/cmd/gcs-sidecar/main.go index 4a23c93c28..f6205bbc60 100644 --- a/cmd/gcs-sidecar/main.go +++ b/cmd/gcs-sidecar/main.go @@ -26,6 +26,8 @@ import ( sidecar "github.com/Microsoft/hcsshim/internal/gcs-sidecar" ) +var vsmbKeepAliveHandle windows.Handle + var ( defaultLogFile = "C:\\gcs-sidecar-logs.log" defaultLogLevel = "trace" @@ -182,8 +184,8 @@ func main() { } } - logrus.Println("Initializing VSMB redirector..") - sidecar.VsmbMain() + logrus.Println("Initializing VSMB redirector!!!") + sidecar.VsmbMain(&vsmbKeepAliveHandle) // 1. Start external server to connect with inbox GCS listener, err := winio.ListenHvsock(&winio.HvsockAddr{ diff --git a/internal/gcs-sidecar/vsmb.go b/internal/gcs-sidecar/vsmb.go index 4b0c18ea8a..6a2215c45b 100644 --- a/internal/gcs-sidecar/vsmb.go +++ b/internal/gcs-sidecar/vsmb.go @@ -27,6 +27,9 @@ const ( LmrInstanceFlagAllowGuestAuth = 0x8 LmrInstanceFlagSupportsDirectmappedIo = 0x10 SmbCeTransportTypeVmbus = 3 + + FileReadAttributes = 0x00000080 + FileFlagBackupSemantics = 0x02000000 ) type IOStatusBlock struct { @@ -166,7 +169,7 @@ func isLanmanWorkstationRunning() (bool, error) { return status.State == svc.Running, nil } -func VsmbMain() { +func VsmbMain(vsmbKeepAliveHandle *windows.Handle) { logrus.Info("Starting VSMB initialization...") logrus.Debug("Configuring LanmanWorkstation service...") @@ -329,4 +332,31 @@ func VsmbMain() { } else { logrus.Errorf("NtFsControlFile failed: 0x%08X", status) } + + const ( + device = `\\?\GLOBALROOT\Device\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\defaultEmptyShare` + ) + + devicePtr, nerr := windows.UTF16PtrFromString(device) + if nerr != nil { + logrus.WithError(nerr).Errorf("invalid device name %q", device) + return + } + vsmbHandle, err := windows.CreateFile( + devicePtr, + FileReadAttributes, + windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, + nil, + windows.OPEN_EXISTING, + FileFlagBackupSemantics, + 0, + ) + + if err != nil { + logrus.WithError(err).Errorf("Failed to open %s", device) + return + } + + *vsmbKeepAliveHandle = vsmbHandle + logrus.Infof("VSMB connection will be alive...") } diff --git a/internal/uvm/create.go b/internal/uvm/create.go index c3d5cb0675..8d6c8c839a 100644 --- a/internal/uvm/create.go +++ b/internal/uvm/create.go @@ -137,6 +137,7 @@ type ConfidentialCommonOptions struct { SecurityPolicyEnabled bool // Set when there is a security policy to apply on actual SNP hardware, use this rathen than checking the string length SecurityPolicyEnforcer string // Set which security policy enforcer to use (open door or rego). This allows for better fallback mechanic. UVMReferenceInfoFile string // Path to the file that contains the signed UVM measurements + BundleDirectory string // This allows paths to be constructed relative to a per-VM bundle directory. } func verifyWCOWBootFiles(bootFiles *WCOWBootFiles) error { diff --git a/internal/uvm/create_lcow.go b/internal/uvm/create_lcow.go index 4cc23a45ca..5ac388b181 100644 --- a/internal/uvm/create_lcow.go +++ b/internal/uvm/create_lcow.go @@ -92,7 +92,6 @@ const ( type ConfidentialLCOWOptions struct { *ConfidentialCommonOptions UseGuestStateFile bool // Use a vmgs file that contains a kernel and initrd, required for SNP - BundleDirectory string // pod bundle directory DmVerityRootFsVhd string // The VHD file (bound to the vmgs file via embedded dmverity hash data file) to load. DmVerityMode bool // override to be able to turn off dmverity for debugging DmVerityCreateArgs string // set dm-verity args when booting with verity in non-SNP mode diff --git a/internal/uvm/create_wcow.go b/internal/uvm/create_wcow.go index ffa6b6d0a3..f922017b44 100644 --- a/internal/uvm/create_wcow.go +++ b/internal/uvm/create_wcow.go @@ -466,6 +466,30 @@ func prepareSecurityConfigDoc(ctx context.Context, uvm *UtilityVM, opts *Options scsi.Slot{Controller: 0, LUN: 1}, scsi.Slot{Controller: 0, LUN: 2}) + vsmbOpts := &hcsschema.VirtualSmbShareOptions{ + ReadOnly: true, + ShareRead: true, + NoOplocks: true, + } + + // Construct a per-VM share directory relative to the bundle. The directory EmptyDoNotModify should be left empty. + sharePath := filepath.Join(opts.BundleDirectory, "EmptyDoNotModify") + + // Ensure the directory exists. + if err := os.MkdirAll(sharePath, os.ModePerm); err != nil { + return nil, fmt.Errorf("failed to create VSMB default empty share directory %q: %w", sharePath, err) + } + + if err := wclayer.GrantVmAccess(ctx, uvm.id, sharePath); err != nil { + return nil, errors.Wrap(err, "failed to grant vm access to VSMB default empty share directory") + } + + doc.VirtualMachine.Devices.VirtualSmb.Shares = []hcsschema.VirtualSmbShare{{ + Name: "defaultEmptyShare", + Path: sharePath, + Options: vsmbOpts, + }} + return doc, nil }