GCC Stack-Smashing Protector

今天在写kernel的时候碰见这么一个错误,undefined reference to `__stack_chk_fail'
出现错误的地方是在 void disp_Int(int num)调用了,void itoa(char* str, int num).
如果不想使用gcc的堆栈溢出保护可以使用:CFLAGS   add  -fno-stack-protector  when compile

下面是添加保护的代码:

What is it?

The GCC SSP protects the stack from buffer overflows. If a buffer overflow occurs, you're informed instantly. The way this works is by inserting a "canary" value into the stack frame that, if changed, indicates a buffer overflow or stack corruption. This feature can not only detect buffer overflows, malicious or accidental, but also may help in detecting other stack-related bugs that are often found in kernel code.

How does it work?

Suppose you are writing a program to which data is passed by an external program. You may write a function like the following which accepts external data. Obviously this is a contrived example which no one would write in practice, but it demonstrates the idea.

ContractedBlock.gif ExpandedBlockStart.gif View Code
1 int check_input(const char *input)
2 {
3 char buf[16];
4
5 strcpy(buf, input);
6
7 // do some processing and return a value based on it
8 }

Now the stack frame for the above is:

Return EIP
Previous EBP
buf[12-15]
buf[8-11]
buf[4-7]
buf[0-3]

If someone passed a 24 byte value to this function as the input parameter, they could easily overwrite our return EIP and thus redirect our execution to their own malicious code. SSP is designed to protect against this. What it aims to do is insert a special value called a canary into the stack immediately after the return EIP address. On function exit, this is compared against its original value, and if it has been overwritten then execution halts with an error. It is thus able to protect against accidental and malicious buffer overflows that would affect the return address. Of note it doesn't stop one buffer overflowing into another.

The problem is that the canary value cannot be known to the person passing data to our check_input function, as otherwise they could just inject it into their data at the appropriate offset, along with an altered return EIP address, and the SSP mechanism would be none the wiser. To get around this, the gcc implementation uses a random value which is chosen fresh each time a process starts. The actual gcc implementation uses a canary value the size of a pointer and then reads the required number of bytes from /dev/urandom in the start-up code for a process. If it cannot do this, it chooses the value 0x00000aff which is at least effective protection against some attacks using the standard string copying functions (they will stop copying once they reach the null value) and most accidental overflows.

How to implement it

When you started OS developing, you might have seen that following error:

... undefined reference to __stack_chk_fail

... undefined reference to __stack_chk_guard

That's actually the SSP! You probably just didn't care about it and disabled it.

Now, implementing this feature is dead easy and it is a really handy thing.

void * __stack_chk_guard = NULL;
 
void __stack_chk_guard_setup()
{
    unsigned char * p;
    p = (unsigned char *) &__stack_chk_guard;
 
    /* If you have the ability to generate random numbers in your kernel then use them,
       otherwise for 32-bit code: */
    *p =  0x00000aff;
}
 
void __attribute__((noreturn)) __stack_chk_fail()
{ 
    /* put your panic function or similar in here */
    unsigned char * vid = (unsigned char *)0xB8000;
    vid[1] = 7;
    for(;;)
    vid[0]++;
}


Call __stack_chk_guard_setup at early boot stage, from there on you're protected from most buffer overflows.

Don't forget to add -fstack-protector-all to the gcc flags.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值