zoukankan      html  css  js  c++  java
  • 内核栈溢出【转】

    转自:http://linuxperf.com/?p=116

    在Linux系统上,进程运行分为用户态与内核态,进入内核态之后使用的是内核栈,作为基本的安全机制,用户程序不能直接访问内核栈,所以尽管内核栈属于进程的地址空间,但与用户栈是分开的。Linux的内核栈大小是固定的,从2.6.32-520开始缺省大小是16KB,之前的kernel版本缺省大小是8KB。内核栈的大小可以修改,但要通过重新编译内核实现。以下文件定义了它的大小:

    arch/x86/include/asm/page_64_types.h
    8KB:
    #define THREAD_ORDER 1
    16KB:
    #define THREAD_ORDER 2

    由于内核栈的大小是有限的,就会有发生溢出的可能,比如调用嵌套太多、参数太多都会导致内核栈的使用超出设定的大小。内核栈溢出的结果往往是系统崩溃,因为溢出会覆盖掉本不该触碰的数据,首当其冲的就是thread_info — 它就在内核栈的底部,内核栈是从高地址往低地址生长的,一旦溢出首先就破坏了thread_info,thread_info里存放着指向进程的指针等关键数据,迟早会被访问到,那时系统崩溃就是必然的事。kstack-smash

    【小知识】:把thread_info放在内核栈的底部是一个精巧的设计,在高端CPU中比如PowerPC、Itanium往往都保留了一个专门的寄存器来存放当前进程的指针,因为这个指针的使用率极高,然而x86的寄存器太少了,专门分配一个寄存器实在太奢侈,所以Linux巧妙地利用了栈寄存器,把thread_info放在内核栈的底部,这样通过栈寄存器里的指针可以很方便地算出thread_info的地址,而thread_info的第一个字段就是进程的指针。

    内核栈溢出导致的系统崩溃有时会被直接报出来,比如你可能会看到:

    但更多的情况是不直接报错,而是各种奇怪的panic。在分析vmcore的时候,它们的共同点是thread_info被破坏了。以下是一个实例,注意在task_struct中stack字段直接指向内核栈底部也就是thread_info的位置,我们看到thread_info显然被破坏了:cpu的值大得离谱,而且指向task的指针与task_struct的实际地址不匹配:

    作为一种分析故障的手段,可以监控内核栈的大小和深度,方法如下:

    然后检查下列数值,可以看到迄今为止内核栈使用的峰值和对应的backtrace:

    你可以写个脚本定时收集上述数据,有助于找到导致溢出的代码。下面是一个输出结果的实例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    # cat /sys/kernel/debug/tracing/stack_max_size
    7272
    # cat /sys/kernel/debug/tracing/stack_trace
            Depth    Size   Location    (61 entries)
            -----    ----   --------
      0)     7080     224   select_task_rq_fair+0x3be/0x980
      1)     6856     112   try_to_wake_up+0x14a/0x400
      2)     6744      16   wake_up_process+0x15/0x20
      3)     6728      16   wakeup_softirqd+0x35/0x40
      4)     6712      48   raise_softirq_irqoff+0x4f/0x90
      5)     6664      48   __blk_complete_request+0x132/0x140
      6)     6616      16   blk_complete_request+0x25/0x30
      7)     6600      32   scsi_done+0x2f/0x60
      8)     6568      48   megasas_queue_command+0xd1/0x140 [megaraid_sas]
      9)     6520      48   scsi_dispatch_cmd+0x1ac/0x340
    10)     6472      96   scsi_request_fn+0x415/0x590
    11)     6376      32   __generic_unplug_device+0x32/0x40
    12)     6344     112   __make_request+0x170/0x500
    13)     6232     224   generic_make_request+0x21e/0x5b0
    14)     6008      80   submit_bio+0x8f/0x120
    15)     5928     112   _xfs_buf_ioapply+0x194/0x2f0 [xfs]
    16)     5816      48   xfs_buf_iorequest+0x4f/0xe0 [xfs]
    17)     5768      32   xlog_bdstrat+0x2a/0x60 [xfs]
    18)     5736      80   xlog_sync+0x1e0/0x3f0 [xfs]
    19)     5656      48   xlog_state_release_iclog+0xb3/0xf0 [xfs]
    20)     5608     144   _xfs_log_force_lsn+0x1cc/0x270 [xfs]
    21)     5464      32   xfs_log_force_lsn+0x18/0x40 [xfs]
    22)     5432      80   xfs_alloc_search_busy+0x10c/0x160 [xfs]
    23)     5352     112   xfs_alloc_get_freelist+0x113/0x170 [xfs]
    24)     5240      48   xfs_allocbt_alloc_block+0x33/0x70 [xfs]
    25)     5192     240   xfs_btree_split+0xbd/0x710 [xfs]
    26)     4952      96   xfs_btree_make_block_unfull+0x12d/0x190 [xfs]
    27)     4856     224   xfs_btree_insrec+0x3ef/0x5a0 [xfs]
    28)     4632     144   xfs_btree_insert+0x93/0x180 [xfs]
    29)     4488     176   xfs_free_ag_extent+0x414/0x7e0 [xfs]
    30)     4312     224   xfs_alloc_fix_freelist+0xf4/0x480 [xfs]
    31)     4088      96   xfs_alloc_vextent+0x173/0x600 [xfs]
    32)     3992     240   xfs_bmap_btalloc+0x167/0x9d0 [xfs]
    33)     3752      16   xfs_bmap_alloc+0xe/0x10 [xfs]
    34)     3736     432   xfs_bmapi+0x9f6/0x11a0 [xfs]
    35)     3304     272   xfs_iomap_write_allocate+0x1c5/0x3b0 [xfs]
    36)     3032     208   xfs_iomap+0x389/0x440 [xfs]
    37)     2824      32   xfs_map_blocks+0x2d/0x40 [xfs]
    38)     2792     272   xfs_page_state_convert+0x2f8/0x750 [xfs]
    39)     2520      80   xfs_vm_writepage+0x86/0x170 [xfs]
    40)     2440      32   __writepage+0x17/0x40
    41)     2408     304   write_cache_pages+0x1c9/0x4a0
    42)     2104      16   generic_writepages+0x24/0x30
    43)     2088      48   xfs_vm_writepages+0x5e/0x80 [xfs]
    44)     2040      16   do_writepages+0x21/0x40
    45)     2024     128   __filemap_fdatawrite_range+0x5b/0x60
    46)     1896      48   filemap_write_and_wait_range+0x5a/0x90
    47)     1848     320   xfs_write+0xa2f/0xb70 [xfs]
    48)     1528      16   xfs_file_aio_write+0x61/0x70 [xfs]
    49)     1512     304   do_sync_readv_writev+0xfb/0x140
    50)     1208     224   do_readv_writev+0xcf/0x1f0
    51)      984      16   vfs_writev+0x46/0x60
    52)      968     208   nfsd_vfs_write+0x107/0x430 [nfsd]
    53)      760      96   nfsd_write+0xe7/0x100 [nfsd]
    54)      664     112   nfsd3_proc_write+0xaf/0x140 [nfsd]
    55)      552      64   nfsd_dispatch+0xfe/0x240 [nfsd]
    56)      488     128   svc_process_common+0x344/0x640 [sunrpc]
    57)      360      32   svc_process+0x110/0x160 [sunrpc]
    58)      328      48   nfsd+0xc2/0x160 [nfsd]
    59)      280      96   kthread+0x96/0xa0
    60)      184     184   child_rip+0xa/0x20
  • 相关阅读:
    Java入门系列-10-数组
    Java入门系列-09-循环结构
    Java入门系列-08-选择结构
    Java入门系列-07-从控制台中接收输入
    Java入门系列-06-运算符
    05-数据类型和类型转换
    004 java中的变量
    Filter过滤器实现同一地址手机和电脑页面不同
    Java 8 Lambda表达式10个示例【存】
    Centos7+Apache2.4+php5.6+mysql5.5搭建Lamp环境——为了wordPress
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/8566384.html
Copyright © 2011-2022 走看看