a very occasional diary.

nondescript

Labels

2005-08-11

kernel stack overflow.


Linux kernel traditionally has very spartan run-time environment. This is because kernel code is only written by real programmers, impeccable thinkers with boundless capacity for analysis, like yours... err, I got carried away.

In particular, in good old days, when world was simpler, kernel thread stack size used to be just 8K (two 4K pages) on x86. As kernel grew larger, and started to employ more complex algorithms, kernel stack of course shrunk. Right---shrunk: now it is 4K (one page) by default. This was justified by the following considerations:

  • In newer kernels, interrupts can be served on special per-processor interrupt stack (not all architectures allow this, though).
  • Linux slab allocator is efficient and scalable enough to dynamically allocate many data-structures that used to be allocated on the stack.
  • Main reason is that allocation of stacks larger than page size --which is the basic allocation unit of low-level buddy allocator--, fragments page allocator bitmaps, and can lead to out-of-memory situations. With large number of threads this problems becomes severe.

But I digressed again: to-day I got stack overflow in UML configured with CONFIG_KERNEL_STACK_ORDER=3, that is with stack occupying 2**3 = 8 pages (32K)!:

stack
0xa005632c __alloc_pages+636
0xa02172e4 sigemptyset+36
0xa0056427 __get_free_pages+39
0xa00599d8 cache_grow+152
0xa0059d48 cache_alloc_refill+312
0xa005a0cd __kmalloc+125
0xa01a0e58 alloc_skb+72
0xa00257e6 uml_net_rx+38
0xa002595f uml_net_interrupt+47
0xa0016b05 handle_IRQ_event+53
0xa0016cb6 do_IRQ+118
0xa001748a sigio_handler+218
0xa0021b31 sig_handler_common_tt+161
0xa001bf20 enable_mask+80
0xa001de48 sig_handler+24
0xa0217098 __restore
0xa0217212 __sigprocmask+34
0xa001bdda change_sig+90
0xa001be63 change_signals+115
0xa00173ed sigio_handler+61
0xa0021b31 sig_handler_common_tt+161
0xa001de48 sig_handler+24
0xa0217098 __restore
0xa0217212 __sigprocmask+34
0xa001bf20 enable_mask+80
0xa02172e4 sigemptyset+36
0xa001c011 set_signals+129
0xa001be63 change_signals+115
0xa001bf20 enable_mask+80
0xa02172e4 sigemptyset+36
0xa001c011 set_signals+129
0xa001bf68 get_signals+40
0xa005a098 __kmalloc+72
0xa01a0e58 alloc_skb+72
0xa01d2062 tcp_send_ack+50
0xa01cdb04 tcp_rcv_established+612
0xa01d67da tcp_v4_do_rcv+282
0xa01d6e0c tcp_v4_rcv+1580
0xa001bf20 enable_mask+80
0xa02172e4 sigemptyset+36
0xa01bb21a ip_local_deliver+282
0xa01bb706 ip_rcv+870
0xa01a62c5 netif_receive_skb+389
0xa01a63a7 process_backlog+135
0xa01a64b6 net_rx_action+118
0xa003c1b5 __do_softirq+165
0xa003c205 do_softirq+69
0xa0016d0b do_IRQ+203
0xa001748a sigio_handler+218
0xa0021b31 sig_handler_common_tt+161
0xa001be63 change_signals+115
0xa001de48 sig_handler+24
0xa0217098 __restore
0xa0217212 __sigprocmask+34
0xa003c1fe do_softirq+62
0xa0016d0b do_IRQ+203
0xa00173ed sigio_handler+61
0xa0021b31 sig_handler_common_tt+161
0xa001de48 sig_handler+24
0xa0217098 __restore
0xa0217212 __sigprocmask+34
0xa02172e4 sigemptyset+36
0xa001be63 change_signals+115
0xa001bec2 unblock_signals+18
0xa0050aaa find_get_pages_tag+122
0xa005b9d3 pagevec_lookup_tag+51
0xa001bfd5 set_signals+69
0xa001be63 change_signals+115
0xa001bf74 get_signals+52
0xa0058147 mapping_tagged+55
0xa008e841 wake_up_inode+17
0xa00945d1 __sync_single_inode+161
0xa008e387 iput+87
0xa0094932 sync_sb_inodes+450
0xa001c011 set_signals+129
0xa0094af0 writeback_inodes+160
0xa005766a wb_kupdate+186
0xa02172e4 sigemptyset+36
0xa005822f __pdflush+207
0xa001bec2 unblock_signals+18
0xa0058310 pdflush
0xa0058339 pdflush+41
0xa00575b0 wb_kupdate
0xa0058310 pdflush
0xa004aee9 kthread+169
0xa004ae40 kthread
0xa0019909 run_kernel_thread+73
0xa02172e4 sigemptyset+36
0xa004ae40 kthread
0xa00198ee run_kernel_thread+46
0xa004ae40 kthread
0xa001fa50 new_thread_handler+304
0xa004ae40 kthread
0xa001fa90 new_thread_proc
0xa0217098 __restore
0xa001fa90 new_thread_proc
0xa022faad syscall+29
0xa022fab1 syscall+33

Of course, UML is unusual platform: it doesn't support separate interrupt stack, and interrupt trampoline code (including host signal frames) is expensive stack-wise, but still: beware of stack consumption.

--Tags:-[]-[]-----------

Follow by Email