整理 | 苏宓
近日,据外媒 phoronix 报道,在最新的 Linux 6.6-rc6 内核测试版本发布之前,不少开发者都遇到了一个令人相当尴尬的 Bug,即只要用户拔下罗技鼠标的 USB 接收器,就会导致 Linux 内核崩溃。
在发现这一问题之后,红帽公司的 Hans de Goede 工程师开始负责处理这一罗技 USB 接收器断开连接的错误,包括 USB 断开连接导致内核崩溃、USB 上的 power_supply_uevent 导致 page_fault_oops、内核模块 hid_logitech_dj 导致崩溃和 USB 损坏、罗技统一接收器无法正常工作等。
之所以会发生这样的错误,Hans de Goede 在修复接收器 USB 断开时导致内核崩溃的补丁中解释道:hidpp_connect_event()有四个检查时间与使用时间(TOCTOU)的冲突。
其中,hidpp_connect_event() 主要从工作队列运行,但它也在 probe() 上运行,如果当从 probe() 运行 hidpp_connect_event() 的线程在硬件上等待时,硬件收到了一个 "设备连接 "数据包,那么将从工作队列启动第二个运行 hidpp_connect_event() 的线程。
正如上文所述,这就会带来四种不一样的情况:
1. 读取 + 打印协议(无害冲突):
if (!hidpp->protocol_major) {
hidpp_root_get_protocol_version()
hidpp->protocol_major = response.rap.params[0];
}
实际上,我们可以在 rhbz#2227968 所附的 abrt 输出中的 dmesg 中看到这种冲突:
[ 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.
添加了额外日志的测试表明,在此之后,2 个线程会轮流抓取硬件访问互斥项 (send_mutex),未来的某个时间、某个案例中,便会存在这种 Bug。
2. 将名称更新为 HIDPP 名称(无害冲突):
if (hidpp->name == hdev->name) {
...
hidpp->name = new_name;
}
3. 为电池初始化 power_supply 类(有问题!):
hidpp_initialize_battery()
{
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);
}
4. 创建延迟输入设备(可能存在问题):
if (hidpp->delayed_input)
return;
hidpp->delayed_input = hidpp_allocate_input(hdev);
这里最大的问题出现在第三种情况上。冲突会导致以下结果:
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);
目前针对这个 Bug 的修复已经合并到本周的 Linux 6.6-rc6 版本的 HID 修复中,并将在接下来的几天内迁移到 Linux 稳定版。
与此同时,如果你使用的是最新的 Linux 内核版本,请不要拔下你的罗技 USB 接收器,以避免可能导致内核崩溃。
来源:https://www.phoronix.com/news/Logitech-USB-Unplug-Linux-Crash
推荐阅读:
▶ 苹果承认iPhone 15系列存在烧屏问题,但拒绝召回;Win11用户量将达5亿;Node.js 21发布 | 极客头条
▶编写一个 “Hello World” 的 Web 服务器,Go、Node.js、Nim 和 Bun 谁更快?