Table of Contents
Linux Stack Overflow and Buffer Over
| Reference | 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
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


