“stack smashing detected” How it works??

Recently i was thinking about on how does the canary work in Linux Glibc. Later i started working on it with a small HelloWorld program which has canary enabled.

#include
int main(){
printf("Hello World\n");
return 0;
}

Complied it with Canary enabled.

gcc -m32 -fstack-protector-all hello.c -o hello

Looking at the disassembly part.

Dump of assembler code for function main:
1   0x0804846d <+0>:	push   ebp
2   0x0804846e <+1>:	mov    ebp,esp
3   0x08048470 <+3>:	and    esp,0xfffffff0
4   0x08048473 <+6>:	sub    esp,0x20
5   0x08048476 <+9>:	mov    eax,gs:0x14
6   0x0804847c <+15>:	mov    DWORD PTR [esp+0x1c],eax
7   0x08048480 <+19>:	xor    eax,eax
8   0x08048482 <+21>:	mov    DWORD PTR [esp],0x8048540
9   0x08048489 <+28>:	call   0x8048340 <puts@plt>
10  0x0804848e <+33>:	mov    eax,0x0
11  0x08048493 <+38>:	mov    edx,DWORD PTR [esp+0x1c]
12  0x08048497 <+42>:	xor    edx,DWORD PTR gs:0x14
13  0x0804849e <+49>:	je     0x80484a5 <main+56>
14  0x080484a0 <+51>:	call   0x8048330 <__stack_chk_fail@plt>
15  0x080484a5 <+56>:	leave  
16  0x080484a6 <+57>:	ret    

When you look at line 5 you could see that some value from global section is moved to $eax and in the next line it is pushed on to the stack. Which is some random value.

Than after the “print” operation there is check of canary value that can be seen in line 11, 12 in the case of same value it is moved to 15th line and then return the program normally. if not   “__stack_chk_fail@plt” library routine is beginning called through the PLT. Lets see what does that function contain.

#include 
#include 
 
extern char **__libc_argv attribute_hidden;
 
void
__attribute__ ((noreturn))
__stack_chk_fail (void)
{
  __fortify_fail ("stack smashing detected");
}

I found this source code form GNU C Library at debug/stack_chk_fail.c Even you can find it from this link

So this code simply calls __fortify_fail with argument “smash the stack”. In the same GNU library i also found fortify_fail.c

#include 
#include 
extern char **__libc_argv attribute_hidden;
void
__attribute__ ((noreturn)) internal_function
__fortify_fail (const char *msg)
{
  /* The loop is added only to keep gcc happy.  */
  while (1)
    __libc_message (2, "*** %s ***: %s terminated\n",
		    msg, __libc_argv[0] ?: "");
}
libc_hidden_def (__fortify_fail)

This program should make clear about the error message, in the case of canary value change.