首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

[linux][kernel]list_del引起的kernle die分析

前言: 构造网络的恶劣环境:中断,恢复,中断,恢复。。。 复现了到kernel die的BUG。经过分析,是对同一个entry执行了两次list_del导致。 Double deletion引起的问题,这里分享一种分析类似问题的方法。 分析: 1,call trace 作者看到了两份不同的call trace,不过它们最后的IP是相同的,有可能是同一个BUG。 需要注意的是,下面两份trace的RIP和RCX寄存器。 CPU: 15 PID: 23529 Comm: lvm Tainted: G D W E 4.14.11 #1 task: ffff91a382b72e00 task.stack: ffffb3928ade8000 RIP: 0010:scsi_device_dev_release_usercontext+0x58/0x200 RSP: 0018:ffffb3928adebb48 EFLAGS: 00010046 RAX: 0000000000000246 RBX: ffff9lad99f95738 RCX: dead000000000100 RDX: dead000000000200 RSI: dead000000000100 RDI: ffff91a3a2e5a030 RBP: ffff9lad99f95138 ROB: 0000000000000101 R09: 00000001810000fe R10: ffffb3928adebb10 R11: 0000000000000000 R12: ffff9lad99f95000 R13: ffff9lac2614b028 R14: ffffffff91328320 R15: ffff9lacef5e3e98 FS: 00007f1ca63c9840(0000) GS:ffff9lad9f3c0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CRO: 0000000080050033 CR2:000000c42027d000 CR3:0000000cb5e06002 CR4:00000000003626e0 DRO:0000000000000000 DR1:0000000000000000 DR2:0000000000000000 DR3:0000000000000000 DR6:00000000fffeOff0 DR7:0000000000000400 CallTrace: table_load+0x360/0x360 execute_in_process_context+0x58/0x60 device_release+Ox2d/0x80 kobject_put+Ox7f/Ox1a0 scsi_disk_put+Ox2b/Ox40 __blkdev_put+Ox19e/Ox1f0 table_load+0x360/0x360 disk_flush_events+0x24/0x60 table_load+0x360/0x360 dm_put_table_device+Ox51/OxbO dm_put_device+0x75/OxbO table_load+0x360/0x360 linear_dtr+0x12/0x20 dm_table_destroy+0x66/0x110 table_load+0x360/0x360 dev_suspend+Oxde/0x250 ctl_ioctl+0x1c0/0x480 dm_ctl_ioctl+Oxa/Ox10 do_vfs_ioctl+0x9f/Ox5f0 Sys_ioctl+0x74/0x80 CPU: 25 PIO: 2084 Comm: kworker/u64:6 Tainted: G W E 4.14.11 #1 WorkqueLm: scsi_wq_18 __iscsi_unbind_session [scsi_transport_iscsi] task: ffff91255ed74500 task.stack: ffffad74c97cc000 RIP: 0010:scsi_device_dev_release_usercontext.0x58/0x200 RSP: 0018:f f f fad74c97cfd80 EFLAGS: 00010046 PAX: 0000000000000246 RBX: ffff912695682f38 RCX: dead000000000100 BOX: dead000000000200 RSI: dead000000000100 ROI: ffff9125e9529030 RBP: ffff912695682938 R08: 00000000ffffffff R09: ffff9126967b5220 R10: 000000000000029f R11: 0000000000000000 R12: ffff912695682800 R13: ffff911f4faef028 R14: ffff912695682800 R15: ffff9125e9529010 FS: 0000000000000000(0000) GS:ffff91269f440000(0000) knIGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CRO: 0000000080050033 CR2: 00007f90027ef020 CR3: 00000002e640a006 CR4: 00000000003626e0 Call Trace: execute_in_process_context.0x58/0x60 device_release.0x2d/Ox80 kobject_put.0x7f/Ox1a0 scsi_remoue_target.0x171/0x1b0 __iscsi_unbind_session.0x63/0x160 [scsi_transport_iscsi] process_one_work.0x151/0x3f0 worker_thread.0x4a/Ox440 kthread.Oxfc/Ox130 process_one_work.0x3f0/0x3f0 kthread_create_on_node.0x70/0x70 do_group_exit.0x3a/Oxa0 ret_from_fork.0x1f/Ox30 Code: f8 ff ff 4c 8b ab 40 fa ff ff 48 8b 78 38 e8 60 d5 2a 00 48 8b 8b d8 f8 ff ff 48 8b 93 e0 f8 ff ff 48 be 00 ad de <48> 89 51 08 48 89 Oa 48 8b 8b e8 f8 ff ff 48 8b 93 f0 f8 ff ff RIP: scsi device dev release usercontext.0x58/0x200 RSP: ffffad74c97cfd80 2,RIP 先来分析RIP。在shell中执行: grep scsi_device_dev_release_usercontext /boot/System.map-4.14.11 可以得到scsi_device_dev_release_usercontext的起始地址是ffffffff8162c400。 出现错误的地址就是:0xffffffff8162c400 + 0x58 = 0xffffffff8162c458。 那么,执行:addr2line -e vmlinux -a 0xffffffff8162c458 可以得到出错的函数就是include/linux/list.h:105

因为是inline函数,所以找到scsi_device_dev_release_usercontext 的代码:

3,objdump 很不幸,因为inline的关系,还不能从RIP中判断出是执行了哪一行的list_del。 使用objdump来dump出来汇编代码继续分析,考虑到dump整个vmlinux比较费时间,作者写了一个脚本,用来只dump一个函数。地址在https://github.com/pacepi/tool/objdump-function.sh中,用法: objdump-function.sh vmlinux scsi_device_dev_release_usercontext

4,RCX 结合上文的汇编代码,可以判断出来,出现问题的地方就是list_del(&sdev->siblings); 继续查看list_del的代码: 在list del执行之后,会把entry的next设置成为一个特殊的magic number。查看宏定义可以发现LIST_POISON1是dead000000000100。 结合汇编代码,以及RCX寄存器的值刚好就是dead000000000100。 说明,在执行list_del(&sdev->siblings)之前, sdev->siblings已经从list中删除了。 5,patch 作者暂时做了一个patch:

作者把patch发送给maintainer了。maintainer回复了mail: Please retest with kernel v4.15-rc6 or later. That kernel includes commit 81b6c9998979 ("scsi: core: check for device state in __scsi_remove_target()").

好吧,当时搜索commit的时候,没看到这个@@

这次的分析过程不能作为这个问题的最终解决办法,算是一个分析类似问题的过程。

举报
领券