-
-
Notifications
You must be signed in to change notification settings - Fork 75
Description
Describe the bug
This came up in crc-org/vfkit#373 (comment)
The code roughly does:
f, err := os.OpenFile(devPath, open_flags, 0)
if err != nil {
return nil, fmt.Errorf("error opening file: %v", err)
}
attachment, err := vz.NewDiskBlockDeviceStorageDeviceAttachment(f, conf.ReadOnly, vz.DiskSynchronizationModeFull)
if err != nil {
_ = f.Close()
return nil, fmt.Errorf("error creating disk attachment: %v", err)
}
// create device with attachment and add it to VM
After this function returns, f can be garbage collected at any time, which will close its file descriptor.
The relevant code in Code-Hex/vz is https://github.com/Code-Hex/vz/blob/c17cd79c8418115e1fcbf98c78f53bc62fd0c972/storage.go#L384C6-L408 , it uses file.Fd() directly, and then it’s used as
Lines 40 to 53 in c17cd79
| void *newVZDiskBlockDeviceStorageDeviceAttachment(int fileDescriptor, bool readOnly, int syncMode, void **error) | |
| { | |
| #ifdef INCLUDE_TARGET_OSX_14 | |
| if (@available(macOS 14, *)) { | |
| NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor]; | |
| return [[VZDiskBlockDeviceStorageDeviceAttachment alloc] | |
| initWithFileHandle:fileHandle | |
| readOnly:(BOOL)readOnly | |
| synchronizationMode:(VZDiskSynchronizationMode)syncMode | |
| error:(NSError *_Nullable *_Nullable)error]; | |
| } | |
| #endif | |
| RAISE_UNSUPPORTED_MACOS_EXCEPTION(); | |
| } |
I don’t think
NSFileHandle *fileHandle = [[NSFileHandle alloc] initWithFileDescriptor:fileDescriptor]; will dup() the file descriptor.
The end result is that we’ll be getting errors such as this when f gets closed prematurely:
NSLocalizedFailure = "Invalid virtual machine configuration.";
NSLocalizedFailureReason = "The storage device attachment is invalid."
This is a bit misleading as the doc says The file handle is retained by the disk attachment.
To Reproduce
I don’t have an easy reproducer, but storage_test.go can probably trigger this in a new test case for block devices and artificial calls to runtime.GC().
The vfkit reproducer is described at crc-org/vfkit#373 (comment) but has been fixed in the latest iteration (crc-org/vfkit#373 (comment))
Expected behavior
Either NewDiskBlockDeviceStorageDeviceAttachment() works fine even if the *os.File argument is closed after it completes, or its documentation changed to explicitly say that *os.File must not be closed/garbage collected while the attachment is in use.