start_kernel——boot_init_stack_canary

/*
 * Initialize the stackprotector canary value.
 *
 * NOTE: this must only be called from functions that never return,
 * and it must always be inlined.
 */
static __always_inline void boot_init_stack_canary(void)
{
    u64 canary;
    u64 tsc;

#ifdef CONFIG_X86_64
    BUILD_BUG_ON(offsetof(union irq_stack_union, stack_canary) != 40);
#endif
    /*
     * We both use the random pool and the current TSC as a source
     * of randomness. The TSC only matters for very early init,
     * there it already has some randomness on most systems. Later
     * on during the bootup the random pool has true entropy too.
     */
    get_random_bytes(&canary, sizeof(canary));
    tsc = __native_read_tsc();
    canary += tsc + (tsc << 32UL);

    current->stack_canary = canary;
#ifdef CONFIG_X86_64
    this_cpu_write(irq_stack_union.stack_canary, canary);
#else
    this_cpu_write(stack_canary.canary, canary);
#endif
}

该函数主要用于初始化“金丝雀“——canary的值。
用于防止栈溢出攻击。

关于栈溢出攻击,有两篇非常好的文章:
http://www.ibm.com/developerworks/cn/linux/l-overflow/
http://blog.aliyun.com/1126

get_random_bytes获取一个内核随机数,赋值给canary。


__native_read_tsc返回一个与TSC相关的数值。


TSC:Time Stamp Counter,是Linux下三种时钟的一种,也是CPU里面的一个64位的寄存器,每一个CPU时钟周期其数值加1.

canary += tsc + (tsc << 32UL);

终于得到canary的值,并将其赋值给current->stack_canary——当前进程的stack_canary成员。

通常採用两种方法防止栈缓冲溢出:
1 发生栈缓冲溢出时将其检測出来。从而阻止通过恶意代码更改指令指针;
2 未直接检測栈缓冲溢出的情况下,预防恶意代码攻击。

stack canary技术属于第一中方法的一种。在恶意代码运行前,可以发现栈缓冲溢出。


程序启动时,canary的值被保存在函数返回地址之前。大部分栈缓冲溢出攻击是从内存的低位向高位覆写内存,所以为了覆写返回地址。必须覆写canary。
所以在使用返回地址之前,查看canary的值。就行确认是否发生了栈缓冲溢出攻击。

posted @ 2016-01-24 12:15  mengfanrong  阅读(679)  评论(0编辑  收藏  举报