如何在内核中找到USB设备增删的Hook点(eBPF实践)
问题解答
你的方法问题所在
你直接搜索usb_driver结构体中probe/disconnect的调用者找不到,核心原因是这两个是函数指针——内核通过动态指针调用这些驱动提供的函数,而非直接硬编码函数名调用,所以静态文本搜索或IDE静态分析无法定位到直接的调用点。
找到USB设备增删的合适Hook点
1. 优先使用内核Tracepoints(最稳定)
USB子系统提供了官方稳定的tracepoint,这些是内核专门为追踪设计的,不会随内核版本频繁变动,是最佳选择:
- 设备添加:
usb_device_add - 设备移除:
usb_device_remove
这些tracepoint定义在内核源码的include/trace/events/usb.h中,你可以用eBPF的tracepoint类型程序直接挂载,能获取到USB设备的核心信息(如设备ID、总线号等)。
2. 用Kprobe挂载USB子系统的顶层/框架函数
如果一定要用kprobe,不要直接找驱动的probe指针,而是找内核中调用这些指针的框架函数,这些函数是固定存在的:
- 设备添加时:
usb_probe_device(位于drivers/usb/core/driver.c),它会最终调用usb_driver->probe - 设备移除时:
usb_unbind_interface(同样在drivers/usb/core/driver.c),它会调用usb_driver->disconnect
另外,也可以挂载更顶层的入口函数,比如设备添加的usb_new_device、设备移除的usb_disconnect,这些函数是USB设备接入/断开时的核心处理入口。
3. 内核动态追踪工具辅助定位
可以先用perf工具确认可用的追踪点:
- 查看USB相关的tracepoint:
perf list 'usb:*' - 验证目标内核函数存在:
perf probe -x /path/to/vmlinux 'usb_probe_device',确认后再编写eBPF程序。
eBPF替代方案
1. Tracepoint替代Kprobe
如前所述,tracepoint是官方稳定接口,比kprobe更可靠,能避免内核版本升级导致函数签名变化的问题。
2. Uprobe插桩用户态udev
如果你想练习uprobe,可以插桩udev的核心处理函数,比如udev处理设备添加事件的udev_device_process_add,或从sysfs读取设备信息的相关函数。这种方式是在用户态捕获事件,相比内核态的tracepoint/kprobe可能有轻微延迟,但适合练习uprobe的使用。
内容的提问来源于stack exchange,提问作者Yang Hanlin
相关产品推荐
相关产品推荐

