Skip to content

Commit 7367837

Browse files
authored
Merge pull request #2591 from pomahade/main
VSMB fix bugcheck by keeping handle open to empty default share
2 parents d97b376 + ccdee31 commit 7367837

File tree

6 files changed

+74
-12
lines changed

6 files changed

+74
-12
lines changed

cmd/containerd-shim-runhcs-v1/pod.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ func createPod(ctx context.Context, events publisher, req *task.CreateTaskReques
187187
}
188188
case *uvm.OptionsWCOW:
189189
wopts := (opts).(*uvm.OptionsWCOW)
190+
wopts.BundleDirectory = req.Bundle
190191
err = initializeWCOWBootFiles(ctx, wopts, req.Rootfs, s)
191192
if err != nil {
192193
return nil, err

cmd/gcs-sidecar/main.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import (
2626
sidecar "github.com/Microsoft/hcsshim/internal/gcs-sidecar"
2727
)
2828

29+
var vsmbKeepAliveHandle windows.Handle
30+
2931
var (
3032
defaultLogFile = "C:\\gcs-sidecar-logs.log"
3133
defaultLogLevel = "trace"
@@ -182,8 +184,13 @@ func main() {
182184
}
183185
}
184186

185-
logrus.Println("Initializing VSMB redirector..")
186-
sidecar.VsmbMain()
187+
logrus.Println("Initializing VSMB redirector!!!")
188+
var vsmbError error
189+
vsmbKeepAliveHandle, vsmbError = sidecar.VsmbMain()
190+
// For now just log the error again instead of failing.
191+
if (vsmbError != nil) || (vsmbKeepAliveHandle == windows.InvalidHandle) {
192+
logrus.WithError(vsmbError).Errorf("VSMB redirector initialization failed.")
193+
}
187194

188195
// 1. Start external server to connect with inbox GCS
189196
listener, err := winio.ListenHvsock(&winio.HvsockAddr{

internal/gcs-sidecar/vsmb.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ const (
2727
LmrInstanceFlagAllowGuestAuth = 0x8
2828
LmrInstanceFlagSupportsDirectmappedIo = 0x10
2929
SmbCeTransportTypeVmbus = 3
30+
31+
FileReadAttributes = 0x00000080
32+
FileFlagBackupSemantics = 0x02000000
3033
)
3134

3235
type IOStatusBlock struct {
@@ -166,13 +169,13 @@ func isLanmanWorkstationRunning() (bool, error) {
166169
return status.State == svc.Running, nil
167170
}
168171

169-
func VsmbMain() {
172+
func VsmbMain() (windows.Handle, error) {
170173
logrus.Info("Starting VSMB initialization...")
171174

172175
logrus.Debug("Configuring LanmanWorkstation service...")
173176
if err := configureAndStartLanmanWorkstation(); err != nil {
174177
logrus.Errorf("LanmanWorkstation setup failed: %v", err)
175-
return
178+
return windows.InvalidHandle, err
176179
}
177180

178181
time.Sleep(3 * time.Second) // TODO: This needs to be better logic.
@@ -187,13 +190,13 @@ func VsmbMain() {
187190

188191
if err := winio.EnableProcessPrivileges([]string{SeLoadDriverName}); err != nil {
189192
logrus.Errorf("Failed to enable privilege: %v", err)
190-
return
193+
return windows.InvalidHandle, err
191194
}
192195
// Open LanmanRedirector
193196
namePtr, nerr := windows.UTF16PtrFromString(GlobalRdrDeviceName)
194197
if nerr != nil {
195198
logrus.WithError(nerr).Errorf("invalid device name %q", GlobalRdrDeviceName)
196-
return
199+
return windows.InvalidHandle, nerr
197200
}
198201

199202
lmrHandle, err := windows.CreateFile(
@@ -207,7 +210,7 @@ func VsmbMain() {
207210
)
208211
if err != nil {
209212
logrus.WithError(err).Error("Failed to open redirector")
210-
return
213+
return windows.InvalidHandle, err
211214
}
212215
defer func() {
213216
if derr := windows.CloseHandle(lmrHandle); derr != nil {
@@ -221,7 +224,7 @@ func VsmbMain() {
221224
instanceNameUTF16, nerr := windows.UTF16FromString(GlobalVsmbInstanceName)
222225
if nerr != nil {
223226
logrus.WithError(nerr).Errorf("invalid instance name %q", GlobalVsmbInstanceName)
224-
return
227+
return windows.InvalidHandle, nerr
225228
}
226229
structSize := int(unsafe.Sizeof(LMRStartInstanceRequest{}))
227230
bufferSize := structSize + (len(instanceNameUTF16)-1)*2
@@ -276,7 +279,7 @@ func VsmbMain() {
276279
namePtr, nerr = windows.UTF16PtrFromString(GlobalVsmbDeviceName)
277280
if nerr != nil {
278281
logrus.WithError(nerr).Errorf("invalid device name %q", GlobalVsmbDeviceName)
279-
return
282+
return windows.InvalidHandle, nerr
280283
}
281284
vmsmbHandle, err := windows.CreateFile(
282285
namePtr,
@@ -286,7 +289,7 @@ func VsmbMain() {
286289
)
287290
if err != nil {
288291
logrus.Errorf("Failed to open VMSMB device: %v", err)
289-
return
292+
return windows.InvalidHandle, err
290293
}
291294
defer func() {
292295
if derr := windows.CloseHandle(vmsmbHandle); derr != nil {
@@ -297,7 +300,7 @@ func VsmbMain() {
297300
transportNameUTF16, nerr := windows.UTF16FromString(GlobalVsmbTransportName)
298301
if nerr != nil {
299302
logrus.WithError(nerr).Errorf("invalid instance name %q", GlobalVsmbTransportName)
300-
return
303+
return windows.InvalidHandle, nerr
301304
}
302305

303306
bindStructSize := int(unsafe.Sizeof(LMRBindUnbindTransportRequest{}))
@@ -329,4 +332,31 @@ func VsmbMain() {
329332
} else {
330333
logrus.Errorf("NtFsControlFile failed: 0x%08X", status)
331334
}
335+
336+
const (
337+
device = `\\?\GLOBALROOT\Device\vmsmb\VSMB-{dcc079ae-60ba-4d07-847c-3493609c0870}\defaultEmptyShare`
338+
)
339+
340+
devicePtr, nerr := windows.UTF16PtrFromString(device)
341+
if nerr != nil {
342+
logrus.WithError(nerr).Errorf("invalid device name %q", device)
343+
return windows.InvalidHandle, nerr
344+
}
345+
vsmbHandle, err := windows.CreateFile(
346+
devicePtr,
347+
FileReadAttributes,
348+
windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE,
349+
nil,
350+
windows.OPEN_EXISTING,
351+
FileFlagBackupSemantics,
352+
0,
353+
)
354+
355+
if err != nil {
356+
logrus.WithError(err).Errorf("Failed to open %s", device)
357+
return windows.InvalidHandle, err
358+
}
359+
360+
logrus.Infof("VSMB connection will be alive...")
361+
return vsmbHandle, nil
332362
}

internal/uvm/create.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ type ConfidentialCommonOptions struct {
137137
SecurityPolicyEnabled bool // Set when there is a security policy to apply on actual SNP hardware, use this rathen than checking the string length
138138
SecurityPolicyEnforcer string // Set which security policy enforcer to use (open door or rego). This allows for better fallback mechanic.
139139
UVMReferenceInfoFile string // Path to the file that contains the signed UVM measurements
140+
BundleDirectory string // This allows paths to be constructed relative to a per-VM bundle directory.
140141
}
141142

142143
func verifyWCOWBootFiles(bootFiles *WCOWBootFiles) error {

internal/uvm/create_lcow.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,6 @@ const (
9292
type ConfidentialLCOWOptions struct {
9393
*ConfidentialCommonOptions
9494
UseGuestStateFile bool // Use a vmgs file that contains a kernel and initrd, required for SNP
95-
BundleDirectory string // pod bundle directory
9695
DmVerityRootFsVhd string // The VHD file (bound to the vmgs file via embedded dmverity hash data file) to load.
9796
DmVerityMode bool // override to be able to turn off dmverity for debugging
9897
DmVerityCreateArgs string // set dm-verity args when booting with verity in non-SNP mode

internal/uvm/create_wcow.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,30 @@ func prepareSecurityConfigDoc(ctx context.Context, uvm *UtilityVM, opts *Options
466466
scsi.Slot{Controller: 0, LUN: 1},
467467
scsi.Slot{Controller: 0, LUN: 2})
468468

469+
vsmbOpts := &hcsschema.VirtualSmbShareOptions{
470+
ReadOnly: true,
471+
ShareRead: true,
472+
NoOplocks: true,
473+
}
474+
475+
// Construct a per-VM share directory relative to the bundle. The directory EmptyDoNotModify should be left empty.
476+
sharePath := filepath.Join(opts.BundleDirectory, "EmptyDoNotModify")
477+
478+
// Ensure the directory exists.
479+
if err := os.MkdirAll(sharePath, os.ModePerm); err != nil {
480+
return nil, fmt.Errorf("failed to create VSMB default empty share directory %q: %w", sharePath, err)
481+
}
482+
483+
if err := wclayer.GrantVmAccess(ctx, uvm.id, sharePath); err != nil {
484+
return nil, errors.Wrap(err, "failed to grant vm access to VSMB default empty share directory")
485+
}
486+
487+
doc.VirtualMachine.Devices.VirtualSmb.Shares = []hcsschema.VirtualSmbShare{{
488+
Name: "defaultEmptyShare",
489+
Path: sharePath,
490+
Options: vsmbOpts,
491+
}}
492+
469493
return doc, nil
470494
}
471495

0 commit comments

Comments
 (0)