Wednesday, March 26, 2014

Stack Usage Static Analysis


Stack usage analysis for User Space Applications

Stack size limit for user space processes is typically large (8MB) as opposed to kernel threads. So, static analysis for stack size for user space applications is not typically done. But, 

  • checkscript.plcheckscript.pl is a tool used to finc static per-function usage for linux kernel. However, I used checkscript.pl on user space applications & it worked. So, this can be used to analyze per-function stack usage.

root@babu-VirtualBox:~/tools/stk_corruption# objdump -D a.out --architecture=i386 | ./checkstack.pl i386
0x0804850b main [a.out]:                  100032
root@babu-VirtualBox:~/tools/stk_corruption#

  • -Wframe-larger-than: the gcc option -Wframe-larger-than can be used to warn against large per-function stack usage.
    • -Wframe-larger-than=len: Warn if the size of a function frame is larger than len bytes. The computation done to determine the stack frame size is approximate and not conservative. The actual requirements may be somewhat greater than len even if you do not get a warning. In addition, any space allocated via alloca, variable-length arrays, or related constructs is not included by the compiler when determining whether or not to issue a warning. 

root@babu-VirtualBox:~/tools/stk_corruption# gcc -Wframe-larger-than=4098 a.c

a.c: In function ‘main’:
a.c:25:1: warning: the frame size of 100016 bytes is larger than 4098 bytes [-Wframe-larger-than=]
 }
 ^
root@babu-VirtualBox:~/tools/stk_corruption# 


Stack usage analysis for Kernel Module or Kernel

Stack size limit for kernel threads is limited (4K, 8K, 16K .. etc). So, static analysis of stack usage of kernel functions is critical to avoid run time stack overflow issues (which also result in heap corruption). I found the following two techniques are useful:

  • checkscript.pl: Once the kernel or kernel modules are compiled, checkscript.pl can be used on the binaries to analyze per-function stack usage.
  • CONFIG_FRAME_WARN: Ofcourse, we can be even more proactive & set a threshold value for this compile macro in linux config file. When this is set, gcc's compile flag -Wframe-larger-than=<value_set_to_config_frame_warn> is included in kernel's compile flags. So, when some function uses stack above this value, a warning is emitted by the compiler. 



root@babu-VirtualBox:~/tools/stk_corruption/lkm/hello_lkm# make
make -C /lib/modules/3.13.5/build M=/home/babu/tools/stk_corruption/lkm/hello_lkm/ modules
make[1]: Entering directory `/usr/src/linux-3.13.5'
  CC [M]  /home/babu/tools/stk_corruption/lkm/hello_lkm/hello.o
/home/babu/tools/stk_corruption/lkm/hello_lkm/hello.c: In function ‘hello_init’:
/home/babu/tools/stk_corruption/lkm/hello_lkm/hello.c:14:1: warning: the frame size of 10004 bytes is larger than 1024 bytes [-Wframe-larger-than=]
 }
 ^
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/babu/tools/stk_corruption/lkm/hello_lkm/hello.mod.o
  LD [M]  /home/babu/tools/stk_corruption/lkm/hello_lkm/hello.ko
make[1]: Leaving directory `/usr/src/linux-3.13.5'
root@babu-VirtualBox:~/tools/stk_corruption/lkm/hello_lkm# 



Comparison: checkscript.pl vs -Wframe-larger-than:

-W-frame-larger-than/CONFIG_FRAME_WARN is nice, but some developers simply ignore the warnings!! Also, we can't dynamically enforce a different per-function stack size threshold without a kernel recompilation. For this reason, I like checkscript.pl better than this option. But, I prefer using both these techniques in a complimentary fashion.


References:
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

No comments:

UA-48797665-1