Linux 内核崩了,只因拔掉罗技的 USB 接收器.....

最新Linux内核遇到罗技鼠标USB断开引发的崩溃问题,HansdeGoede工程师发现hidpp_connect_event的TOCTOU冲突导致内核模块崩溃。已修复并合并至Linux6.6-rc6,建议用户在使用最新内核时避免拔鼠标USB。

97d8dcc8023ffd0a3c5f86fc5705ef2e.gif

整理 | 苏宓

出品 | 优快云(ID:优快云news)

近日,据外媒 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

推荐阅读:

超 50% 程序员考虑辞职,ChatGPT 会是他们的“救星”吗?

同台竞技,厉兵秣马!“移动云杯”复赛一触即发!

一图速览!1024 程序员节亮点抢先看

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值