User Tools

Site Tools


mywiki:linux:linuxstack

Linux Stack Overflow and Buffer Over

kernel Stack

The default stack size for a process running in kernel space is 8K (as of 2011).

exception/hard IRQ/soft IRQ stack

 hardware stack: hardirt_stack array
 softIRQ stack: softirt_stack array

kernel Stack OverFlow

Tools

checkstack.pl

checkstack.pl creates a listing of the size of the stack frame used by every function in the kernel (i.e. the total amount of local scratch space used by each function for local variables and whatnot).

The way it does this is by going through the disassembly of the kernel and looking for 2 things: function names and instructions which adjust the stack. It looks for function names by looking for lines that match $funcre (qr/^$x* <(.*)>:$/), and it looks for stack adjustment instructions that match $re or $dre; the latter two depend highly on what architecture the kernel was compiled for, which is what the first big block if if/else statements is checking for. $re searches for functions which adjust the stack by a fixed amount (the vast majority of functions), and $dre searches for functions which adjust the stack by a variable amount (rare).

$CROSS_COMPILE)objdump -d vmlinux | scripts/checkstack.pl [arch]

Example:

  • mips-openwrt-linux-objdump -d vmlinux | scripts/checkstack.pl mips

Its output like below:

0x803feed4 match [vmlinux]:				3184
0x803fedc8 mangle_http_header.constprop.2 [vmlinux]:	2096
0x80045da8 mtsched_proc_write [vmlinux]:		1088
0x801119c0 do_sys_poll [vmlinux]:			952
0x802fa7ac pce_rule_write [vmlinux]:			848
0x8033daec of_get_dma_window [vmlinux]:			832
0x80110c78 do_select [vmlinux]:				752
0x802ed918 GSW_MulticastRouterPortRemove [vmlinux]:	664
0x802edd68 GSW_MulticastSnoopCfgSet [vmlinux]:		664
...
0x8023ade4 test_comp [vmlinux]:				584
0x8022b4e0 SyS_semtimedop [vmlinux]:			520
0x80038ff8 dma_build_device_chan_tbl [vmlinux]:		504
0x801298ac default_file_splice_read [vmlinux]:		496
0x8023b690 __test_skcipher [vmlinux]:			496
0x80163cd0 elf_kcore_store_hdr [vmlinux]:		464
...
0x80129c08 vmsplice_to_pipe [vmlinux]:			368
0x801aabc8 autofs4_notify_daemon [vmlinux]:		368
0x8034c8b8 skb_splice_bits [vmlinux]:			352
0x800c2c3c show_free_areas [vmlinux]:			344
0x8037053c dev_seq_printf_stats [vmlinux]:		344
0x803b0e8c do_ip_setsockopt.isra.17 [vmlinux]:		344
0x80592c94 init_posix_timers [vmlinux]:			344
0x801111ac core_sys_select [vmlinux]:			336
0x8030adb4 tmu_proc_tmu_cascade_write [vmlinux]:	336
0x803b0214 do_ip_getsockopt.constprop.18 [vmlinux]:	328
0x80122c88 setxattr [vmlinux]:				320
0x80147660 elf_core_dump [vmlinux]:			320
...
0x80396de0 conntrack_pptp_help [vmlinux]:		304

CONFIG_FRAME_WARN

This kernel configuration option passes an option to the compiler to cause it to emit a warning when a static stack size for a routine is detected that is larger than the specified threshold. It requires gcc version 4.4 or later in order to work.

The gcc option used is “-Wframe-larger-than=xxx”.

By default, CONFIG_FRAME_WARN has the value of 1024, but you can set it to any value from 0 to 8192.

Here is a sample of build output with this option configured to 256:

  ...
  CC      ipc/msg.o
  CC      ipc/sem.o
  .../linux-3.0.y/ipc/sem.c: In function 'semctl_main.clone.7':
  .../linux-3.0.y/ipc/sem.c:1021:1: warning: the frame size of 520 bytes is larger than 256 bytes
  .../linux-3.0.y/ipc/sem.c: In function 'sys_semtimedop':
  .../linux-3.0.y/ipc/sem.c:1514:1: warning: the frame size of 472 bytes is larger than 256 bytes
  CC      ipc/shm.o
  CC      ipc/ipcns_notifier.o
  ...

stack_size

Below are some results for static analysis of function stack depth in the Linux kernel, using 'stack_size'. (stack_size is a custom tool written by Tim Bird, before he found out about checkstack.pl.) https://lkml.org/lkml/2011/10/18/479

$ ./stack_size vmlinux-arm

============ RESULTS ===============
number of functions     = 14371
max function stack depth= 736
function with max depth = nlmclnt_reclaim

Function Name                    Stack Depth
=====================            ===========
__generic_file_splice_read        352
do_select                         376
loop_set_status_old               392
snd_ctl_elem_add_user             408
extract_buf                       432
default_file_splice_read          472
sys_semtimedop                    520
semctl_main.clone.7               560
do_sys_poll                       568
nlmclnt_reclaim                   736

CONFIG_DEBUG_STACK_USAGE / CONFIG_DEBUG_STACKOVERFLOW

# dmesg | grep greatest

                                                
kworker/u:0 used greatest stack depth: 10564 bytes left                         
busybox used greatest stack depth: 9512 bytes left                              
busybox used greatest stack depth: 9504 bytes left                              
grep used greatest stack depth: 9372 bytes left                                 
init used greatest stack depth: 9028 bytes left

#echo t >/proc/sysrq-trigger #dmesg | grep -v [[]

 task                PC stack   pid father
init            S 802af8b0   932     1      0 0x00000000
kthreadd        S 802af8b0  2496     2      0 0x00000000
ksoftirqd/0     S 802af8b0  2840     3      2 0x00000000
kworker/0:0     S 802af8b0  2776     4      2 0x00000000
kworker/u:0     S 802af8b0  2548     5      2 0x00000000
migration/0     S 802af8b0  2704     6      2 0x00000000
migration/1     S 802af8b0  2704     7      2 0x00000000
kworker/1:0     S 802af8b0  2560     8      2 0x00000000
ksoftirqd/1     S 802af8b0  3024     9      2 0x00000000
khelper         S 802af8b0  2824    10      2 0x00000000
sync_supers     S 802af8b0  2872    11      2 0x00000000
bdi-default     S 802af8b0  2584    12      2 0x00000000
kblockd         S 802af8b0  2824    13      2 0x00000000
khubd           S 802af8b0  2744    14      2 0x00000000
mywiki/linux/linuxstack.txt · Last modified: by 127.0.0.1