Linux Stack Overflow and Buffer Over
| Reference | [[http://elinux.org/Kernel_Small_Stacks | Linux Kernel Stack]] |
====== 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 ======
{{kernel_stack1.png?400|}}
{{kernel_stack2.png?400|}}
====== 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