工作记录一:netfilter

来源:互联网 发布:本地windows调试器 编辑:程序博客网 时间:2024/06/06 05:39

跳槽到新公司,专门解linux kernel的bug,记录一下工作经历。

主机宕机,/var/crash/vmcore-kdump.txt 如下:


<4>------------[ cut here ]------------
<2>kernel BUG at net/netfilter/nf_conntrack_core.c:206!
<4>invalid opcode: 0000 [#1] SMP
<4>last sysfs file: /sys/devices/system/cpu/cpu47/topology/thread_siblings_list
<4>CPU 0

<4>
<4>Pid: 25449, comm: mebs-nbd-core Tainted: G           --------------- H  2.6.32-431.20.3.el6.mt20161028.x86_64 #1 Dell Inc. PowerEdge R730/0WCJNT
<4>RIP: 0010:[<ffffffffa029b8bc>]  [<ffffffffa029b8bc>] destroy_conntrack+0x11c/0x150 [nf_conntrack]
<4>RSP: 0018:ffff881d10cd99f8  EFLAGS: 00010246

<4>Process mebs-nbd-core (pid: 25449, threadinfo ffff881d10cd8000, task ffff881f0a9b6aa0)
<4>Stack:

<4>Call Trace:
<4> [<ffffffff8148a4c7>] nf_conntrack_destroy+0x17/0x30
<4> [<ffffffffa029bac5>] nf_conntrack_find_get+0x85/0x120 [nf_conntrack]
<4> [<ffffffffa029bdd0>] nf_conntrack_in+0x270/0xa00 [nf_conntrack]
<4> [<ffffffffa023e6e1>] ? ovs_dp_process_received_packet+0x51/0x80 [openvswitch]
<4> [<ffffffffa026c6f1>] ipv4_conntrack_local+0x51/0x60 [nf_conntrack_ipv4]
<4> [<ffffffff8148a439>] nf_iterate+0x69/0xb0
<4> [<ffffffff81498030>] ? dst_output+0x0/0x20
<4> [<ffffffff8148a5f6>] nf_hook_slow+0x76/0x120
<4> [<ffffffff81498030>] ? dst_output+0x0/0x20
<4> [<ffffffff8149a76f>] __ip_local_out+0x9f/0xb0
<4> [<ffffffff8149a796>] ip_local_out+0x16/0x30
<4> [<ffffffff8149ac80>] ip_queue_xmit+0x190/0x420
<4> [<ffffffff8149b4a8>] ? ip_output+0xb8/0xc0
<4> [<ffffffff814aff9e>] tcp_transmit_skb+0x40e/0x7b0
<4> [<ffffffff814b24e0>] tcp_write_xmit+0x230/0xa90
<4> [<ffffffff814b3060>] __tcp_push_pending_frames+0x30/0xe0
<4> [<ffffffff814b3182>] tcp_send_fin+0x72/0x1d0
<4> [<ffffffff814a4586>] tcp_close+0x346/0x450
<4> [<ffffffff814c7fd7>] inet_release+0x67/0x90



因为不熟悉netfilter,所以先花了几天时间去看netfilter(感谢这么多技术大拿分享,节省了很多时间)。同时谷歌搜索发现有很多类似bug。熟悉netfilter之后,结合代码发现问题:

因为使用的是2.6.32内核,netfilter模块里不少bug未解决。。。

定位问题如下:

CPU0                                                      CPU1                                     CPU2

nf_conntrack_in

   nf_conntrack_find_get(USE=1)

                                                         death_by_timeout

                                                             free(ct) (USE=0)

                                                                                                    nf_conntrack_in

                                                                                                        nf_conntrack_find_get

                                                                                                             conntrack_init(USE=1)

atomic_inc_not_zero(USE=2)

                                                                                                   l4proto→new

                                                                                                        free(ct)(USE=0)

                                                                                                   nf_conntrack_in

                                                                                                       nf_conntrack_find_get

                                                                                                           conntrack_init(USE=1)

nf_ct_tuple_equal(USE=1)

    nf_ct_put

       destory_conntrack

          BUG_ON!


假如你未看过netfilter的代码,是很难看懂的。

注意:

CPU2上两次init的ct的地址必须与CPU1上free掉的ct地址一致。

解决方法:

在连接跟踪初始化函数init_conntrack中,将use值初始化为0。然后在l4proto->new函数后,在将连接跟踪加入到unconfiirmed队列之前,将use++。


现在stable版本的内核2.6.32里还未将这个bug解决。。。


这个bug解决用了一周的时间。感想很多:

第一,很感谢小组长的指导,没有他的帮助是不可能这么快就解决的。

第二,看代码一定要动笔写,写出代码逻辑图,架构图。尤其是比较复杂的代码。

第三,困难都是暂时的,只要你努力去做,早晚都能拨云见日。


原创粉丝点击