Version
7.2.6 (r172322). DarwinKeyboard.cpp is byte-identical in 7.2.20; main differs only in $Id/copyright.
Host OS Type
macOS
Host OS name + version
macOS 27.0 (build 26A428)
Host Architecture
arm64
Guest OS Type
Windows
Guest Architecture
arm64
Guest OS name + version
Windows 11 (irrelevant: host-side crash in the GUI process)
Component
GUI
What happened?
VirtualBoxVM crashes with SIGSEGV when the VM window resigns key (click outside it, or switch application) after a HID keyboard was removed from the host while the window had focus. VM state goes to aborted; VBox.log just stops, with no guru meditation and no shutdown sequence.
Three crashes in two days here, identical frames and offsets, fault address 0x0, x0 == 0:
EXC_BAD_ACCESS (SIGSEGV), KERN_INVALID_ADDRESS at 0x0
0 IOKit IOHIDDeviceCopyMatchingElements + 44
1 UICommon.dylib +0x3e6ebc (static darwinSetDeviceLedsState)
2 UICommon.dylib DarwinHidDevicesApplyAndReleaseLedsState + 512
… QApplicationPrivate::setActiveWindow <- QCocoaWindow::windowDidResignKey
Root cause: dangling IOHIDDeviceRef in the LED-sync cache
darwinHidAddDevice() stores the device without retaining it (DarwinKeyboard.cpp:1867). Neither source transfers ownership: the IOHIDManagerCopyDevices() set is released right after the loop (:2041, :2056), the matching callback passes a borrowed reference, and pDeviceCollection has NULL callbacks (:2035). Only the manager's own references remain, and the manager drops them through its own interest notification, independently of the removal callback VirtualBox registers at :1897 (IOKitUser hid.subproj, IOKitUser-100231.100.18.0.1):
IOHIDManager.c:460 IOServiceAddInterestNotification(__IOHIDManagerDeviceRemoved) on manager->notifyPort
IOHIDManager.c:480 device kept as a retained key in removalNotifiers
IOHIDManager.c:671 CFDictionaryRemoveValue(removalNotifiers, sender)
IOHIDManager.c:704 CFSetRemoveValue(manager->devices, sender) -> last reference
HIDDeviceBase.m:46 -dealloc -> _IOHIDDeviceReleasePrivate() (IOHIDDevice.c:292)
IOHIDDevice.c:321 device->deviceInterface = NULL (only place it is zeroed)
IOHIDDevice.c:341 IONotificationPortDestroy(device->notificationPort)
After that, the port darwinHidRemovalCallback() (:1817) would arrive on is gone and the stale entry stays cached. On focus loss DarwinHidDevicesApplyAndReleaseLedsState() -> darwinSetDeviceLedsState(pKbd->pDevice, …) -> IOHIDDeviceCopyMatchingElements(), which does (*device->deviceInterface)->copyMatchingElements(…) (IOHIDDevice.c:676). The shipping IOKit disassembles to +40: ldr x0, [x0, #0x18] (load deviceInterface, struct offset 24) then +44: ldr x8, [x0]; all three reports fault there with x0 == 0. The field sits past the 16-byte free-list header of a freed block, so it still holds the NULL the finalizer wrote, hence 0x0 rather than a random address.
Secondary defect
idxPosition is set at insertion (:1869) and never updated, but CFArrayRemoveValueAtIndex() (:1832) shifts later entries down. With two or more keyboards the callback removes the wrong entry and frees its own. Reachable as soon as the callback actually fires, i.e. once the reference above is taken.
Workaround
VBoxManage setextradata global GUI/HidLedsSync 0 (or per VM). Disables the code path; Caps Lock / Num Lock stop syncing.
Prior reports
Same crash, on Trac since 2019, no root-cause analysis so far:
| Ticket |
Opened |
Status |
| #19153 |
2019-12-13 |
new, last activity 2021-09-20; logs in the comments (6.1.26) show this exact stack at 0x0; comment:5 gives the workaround |
| #19190 |
2019-12-30 |
closed worksforme |
| #21017 |
2022-07-08 |
closed as duplicate of #19153 |
Same stack on the forums: t=86559 (5.2.6), t=102320 (6.1.18), t=107794 (7.0.2).
Fine with closing as a duplicate of #19153; filed here because the fix will come as a GitHub pull request (in preparation). VBox.log and the three .ips reports are available on request (they contain host paths and VM names).
How can we reproduce this?
Any Mac (this one is Apple Silicon; the Trac reports above are x86-64), VirtualBox 7.2.x, HID LEDs sync at its default (enabled). Observed here with the built-in keyboard plus a Bluetooth mouse (VID 0x373E) that also publishes a HID keyboard collection and drops off when idle. GamePolicyAgent lists it as <GCMouse 'R6 Mouse'> next to a <GCKeyboard 'Generic Keyboard'>, loginwindow logs Keyboard Service added on every reconnect (83 and 161 times on the two days in question), and one such reconnect precedes the second crash by 4 s -- which is why no user action was needed. Any terminated kHIDUsage_GD_Keyboard device should do (Bluetooth keyboard going to sleep, USB keyboard unplugged, keyboard captured by a USB filter); the mechanism does not depend on the number of keyboards, but only the Bluetooth-mouse case was exercised here.
- Start a VM and give its window keyboard focus.
- While it has focus, let such a device disappear from the host.
- Click outside the VM window or switch application, so it resigns key.
VirtualBoxVM crashes with the stack above; VM state becomes aborted.
Check for the missing callback: with GUI release logging at level 2, no Forget KBD line (printed by darwinHidRemovalCallback()) appears after step 2.
Version
7.2.6 (r172322).
DarwinKeyboard.cppis byte-identical in 7.2.20;maindiffers only in$Id/copyright.Host OS Type
macOS
Host OS name + version
macOS 27.0 (build 26A428)
Host Architecture
arm64
Guest OS Type
Windows
Guest Architecture
arm64
Guest OS name + version
Windows 11 (irrelevant: host-side crash in the GUI process)
Component
GUI
What happened?
VirtualBoxVMcrashes with SIGSEGV when the VM window resigns key (click outside it, or switch application) after a HID keyboard was removed from the host while the window had focus. VM state goes toaborted;VBox.logjust stops, with no guru meditation and no shutdown sequence.Three crashes in two days here, identical frames and offsets, fault address
0x0,x0 == 0:Root cause: dangling
IOHIDDeviceRefin the LED-sync cachedarwinHidAddDevice()stores the device without retaining it (DarwinKeyboard.cpp:1867). Neither source transfers ownership: theIOHIDManagerCopyDevices()set is released right after the loop (:2041,:2056), the matching callback passes a borrowed reference, andpDeviceCollectionhas NULL callbacks (:2035). Only the manager's own references remain, and the manager drops them through its own interest notification, independently of the removal callback VirtualBox registers at:1897(IOKitUserhid.subproj,IOKitUser-100231.100.18.0.1):After that, the port
darwinHidRemovalCallback()(:1817) would arrive on is gone and the stale entry stays cached. On focus lossDarwinHidDevicesApplyAndReleaseLedsState()->darwinSetDeviceLedsState(pKbd->pDevice, …)->IOHIDDeviceCopyMatchingElements(), which does(*device->deviceInterface)->copyMatchingElements(…)(IOHIDDevice.c:676). The shipping IOKit disassembles to+40: ldr x0, [x0, #0x18](loaddeviceInterface, struct offset 24) then+44: ldr x8, [x0]; all three reports fault there withx0 == 0. The field sits past the 16-byte free-list header of a freed block, so it still holds the NULL the finalizer wrote, hence0x0rather than a random address.Secondary defect
idxPositionis set at insertion (:1869) and never updated, butCFArrayRemoveValueAtIndex()(:1832) shifts later entries down. With two or more keyboards the callback removes the wrong entry and frees its own. Reachable as soon as the callback actually fires, i.e. once the reference above is taken.Workaround
VBoxManage setextradata global GUI/HidLedsSync 0(or per VM). Disables the code path; Caps Lock / Num Lock stop syncing.Prior reports
Same crash, on Trac since 2019, no root-cause analysis so far:
new, last activity 2021-09-20; logs in the comments (6.1.26) show this exact stack at0x0; comment:5 gives the workaroundworksformeSame stack on the forums: t=86559 (5.2.6), t=102320 (6.1.18), t=107794 (7.0.2).
Fine with closing as a duplicate of #19153; filed here because the fix will come as a GitHub pull request (in preparation).
VBox.logand the three.ipsreports are available on request (they contain host paths and VM names).How can we reproduce this?
Any Mac (this one is Apple Silicon; the Trac reports above are x86-64), VirtualBox 7.2.x, HID LEDs sync at its default (enabled). Observed here with the built-in keyboard plus a Bluetooth mouse (VID 0x373E) that also publishes a HID keyboard collection and drops off when idle. GamePolicyAgent lists it as
<GCMouse 'R6 Mouse'>next to a<GCKeyboard 'Generic Keyboard'>,loginwindowlogsKeyboard Service addedon every reconnect (83 and 161 times on the two days in question), and one such reconnect precedes the second crash by 4 s -- which is why no user action was needed. Any terminatedkHIDUsage_GD_Keyboarddevice should do (Bluetooth keyboard going to sleep, USB keyboard unplugged, keyboard captured by a USB filter); the mechanism does not depend on the number of keyboards, but only the Bluetooth-mouse case was exercised here.VirtualBoxVMcrashes with the stack above; VM state becomesaborted.Check for the missing callback: with GUI release logging at level 2, no
Forget KBDline (printed bydarwinHidRemovalCallback()) appears after step 2.