In the Linux kernel, the following vulnerability has been resolved:
HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect
hidppconnectevent() has four time-of-check vs time-of-use (TOCTOU) races when it races with itself.
hidppconnectevent() primarily runs from a workqueue but it also runs on probe() and if a "device-connected" packet is received by the hw when the thread running hidppconnectevent() from probe() is waiting on the hw, then a second thread running hidppconnectevent() will be started from the workqueue.
This opens the following races (note the below code is simplified):
Retrieving + printing the protocol (harmless race):
if (!hidpp->protocolmajor) { hidpprootgetprotocolversion() hidpp->protocolmajor = response.rap.params[0]; }
We can actually see this race hit in the dmesg in the abrt output attached to rhbz#2227968:
[ 3064.624215] logitech-hidpp-device 0003:046D:4071.0049: HID++ 4.5 device connected. [ 3064.658184] logitech-hidpp-device 0003:046D:4071.0049: HID++ 4.5 device connected.
Testing with extra logging added has shown that after this the 2 threads take turn grabbing the hw access mutex (send_mutex) so they ping-pong through all the other TOCTOU cases managing to hit all of them:
Updating the name to the HIDPP name (harmless race):
if (hidpp->name == hdev->name) { ... hidpp->name = new_name; }
Initializing the power_supply class for the battery (problematic!):
hidppinitializebattery() { if (hidpp->battery.ps) return 0;
probe_battery(); /* Blocks, threads take turns executing this */
hidpp->battery.desc.properties =
devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
hidpp->battery.ps =
devm_power_supply_register(&hidpp->hid_dev->dev,
&hidpp->battery.desc, cfg);
}
Creating delayed input_device (potentially problematic):
if (hidpp->delayed_input) return;
hidpp->delayedinput = hidppallocate_input(hdev);
The really big problem here is 3. Hitting the race leads to the following sequence:
hidpp->battery.desc.properties =
devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
hidpp->battery.ps =
devm_power_supply_register(&hidpp->hid_dev->dev,
&hidpp->battery.desc, cfg);
...
hidpp->battery.desc.properties =
devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
hidpp->battery.ps =
devm_power_supply_register(&hidpp->hid_dev->dev,
&hidpp->battery.desc, cfg);
So now we have registered 2 power supplies for the same battery, which looks a bit weird from userspace's pov but this is not even the really big problem.
Notice how:
This causes a use after free scenario on USB disconnect of the receiver: 1. The last registered power supply class device gets unregistered 2. The memory from the last devmkmemdup() call gets freed, hidpp->battery.desc.properties now points to freed memory 3. The first registered power supply class device gets unregistered, this involves sending a remove uevent to userspace which invokes powersupplyuevent() to fill the uevent data 4. powersupply_uevent() uses hidpp->battery.desc.properties which now points to freed memory leading to backtraces like this one:
Sep 22 20:01:35 eric kernel: BUG: unable to handle page fault for address: ffffb2140e017f08
...
Sep 22 20:01:35 eric kernel: Workqueue: usbhubwq hubevent
Sep 22 20:01:35 eric kernel: RIP: 0010:powersupplyuevent+0xee/0x1d0
...
Sep 22 20:01:35 eric kernel: ? asmexcpagefault+0x26/0x30
Sep 22 20:01:35 eric kernel: ? powersupplyuevent+0xee/0x1d0
Sep 22 20:01:35 eric kernel: ? powersupplyuevent+0x10d/0x1d0
Sep 22 20:01:35 eric kernel: devuevent+0x10f/0x2d0
Sep 22 20:01:35 eric kernel: kobjectuevent_env+0x291/0x680
Sep 22 20:01:35 eric kernel:
---truncated---
[
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@cd0e2bf7fb22fe9b989c59c42dca06367fd10e6b",
"id": "CVE-2023-52478-166d7dee",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3324.0,
"function_hash": "231008548842690319328164584729405628666"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@093af62c023537f097d2ebdfaa0bc7c1a6e874e1",
"id": "CVE-2023-52478-2deff2b1",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3684.0,
"function_hash": "188653161833733274378612173203072486428"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@ca0c4cc1d215dc22ab0e738c9f017c650f3183f5",
"id": "CVE-2023-52478-47f78538",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"147646763822239117190424319058521812780",
"195874052998864486124648302200297163294",
"234418784300160559861059007686237477730",
"225500212248627772366431085647952382649"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@dac501397b9d81e4782232c39f94f4307b137452",
"id": "CVE-2023-52478-54a0b173",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3571.0,
"function_hash": "128284316206504796009394934563047650562"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@fd72ac9556a473fc7daf54efb6ca8a97180d621d",
"id": "CVE-2023-52478-6979179e",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3684.0,
"function_hash": "188653161833733274378612173203072486428"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@dac501397b9d81e4782232c39f94f4307b137452",
"id": "CVE-2023-52478-6b2d91b4",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"288805424075359270583652584017913611266",
"44517362999443700044683491796230987883",
"110591519290499630849654272718544638677"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@28ddc1e0b898291323b62d770b1b931de131a528",
"id": "CVE-2023-52478-76e58874",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3684.0,
"function_hash": "188653161833733274378612173203072486428"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@093af62c023537f097d2ebdfaa0bc7c1a6e874e1",
"id": "CVE-2023-52478-80ae50a5",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"288805424075359270583652584017913611266",
"44517362999443700044683491796230987883",
"110591519290499630849654272718544638677"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@44481b244fcaa2b895a53081d6204c574720c38c",
"id": "CVE-2023-52478-8d874273",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3086.0,
"function_hash": "137058750213845836162225659148421945103"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@44481b244fcaa2b895a53081d6204c574720c38c",
"id": "CVE-2023-52478-9947db2c",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"147646763822239117190424319058521812780",
"195874052998864486124648302200297163294",
"234418784300160559861059007686237477730",
"225500212248627772366431085647952382649"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@cd0e2bf7fb22fe9b989c59c42dca06367fd10e6b",
"id": "CVE-2023-52478-9b3200bc",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"327731850048356973943964917340784713065",
"136272313133129177753272990255039947392",
"177947973616120139714516978693914155785"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@ca0c4cc1d215dc22ab0e738c9f017c650f3183f5",
"id": "CVE-2023-52478-a82679bb",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3086.0,
"function_hash": "137058750213845836162225659148421945103"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@fd72ac9556a473fc7daf54efb6ca8a97180d621d",
"id": "CVE-2023-52478-bdfe9914",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"288805424075359270583652584017913611266",
"44517362999443700044683491796230987883",
"110591519290499630849654272718544638677"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@28ddc1e0b898291323b62d770b1b931de131a528",
"id": "CVE-2023-52478-d482ddcb",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"288805424075359270583652584017913611266",
"44517362999443700044683491796230987883",
"110591519290499630849654272718544638677"
]
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@f7b2c7d9831af99369fe8ad9b2a68d78942f414e",
"id": "CVE-2023-52478-d68a7a8e",
"deprecated": false,
"signature_version": "v1",
"target": {
"function": "hidpp_probe",
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Function",
"digest": {
"length": 3571.0,
"function_hash": "128284316206504796009394934563047650562"
}
},
{
"source": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git@f7b2c7d9831af99369fe8ad9b2a68d78942f414e",
"id": "CVE-2023-52478-e0787f22",
"deprecated": false,
"signature_version": "v1",
"target": {
"file": "drivers/hid/hid-logitech-hidpp.c"
},
"signature_type": "Line",
"digest": {
"threshold": 0.9,
"line_hashes": [
"73591266291840289363351651533509420404",
"288805424075359270583652584017913611266",
"44517362999443700044683491796230987883",
"110591519290499630849654272718544638677"
]
}
}
]