Wednesday, March 19, 2008

CLD/STD and GCC 4.3.0

Some of you may have seen this already. Its a very subtle bug that was exposed by GCC 4.3.0 that manifests itself in an interesting way. Heres a quick overview. In its latest version, GCC has changed a very small detail. Before version 4.3.0 GCC would insert a CLD (Clear Direction Flag) instruction before any inline string copy functions as shown below:

804de86: fc cld
804de87: f3 a4 rep movsb %ds:(%esi),%es:(%edi)
804de89: 89 c1 mov %eax,%ecx
804de8b: c1 e9 02 shr $0x2,%ecx

This instruction (CLD) clears a flag that determines which direction data should be written in (forward or backward). The flag itself is stored in the EFLAGS register. Clearing the flag with CLD sets the flag to 0 (forward). The STD instruction can then change this by setting the flag to 1 (backward). GCC no longer emits this instruction before inline string copies. This change is documented here. Technically this is right because the ABI states the direction flag should be cleared before entering any function (see page 38 under EFLAGS). The problem in this case is that the Linux kernel does not clear the flag when entering a signal handler. So in theory the flag is set to 1 for whatever reason and then a signal gets tripped and calls something like memcpy or memmove. Since the CLD instruction is no longer used inline the copy can
write data in the wrong direction. This can obviously lead to security issues. I put together some x86 example code for this based on the x86_64 version posted to LKML, you can find it here.
./cld
Hit Ctrl+C
In signal handler...
DF = 1 (backward)
In signal handler...
DF = 1 (backward)
In signal handler...
DF = 0 (forward)
In signal handler...
DF = 0 (forward)
In signal handler...
DF = 1 (backward)

5 comments:

Anonymous said...
This comment has been removed by a blog administrator.
argp said...

Exactly the same bug was discovered in Google's Native Client in March 2009. User code could set DF in EFLAGS and then request a system call to be executed by the Native Client runtime which did not clear DF before transfering execution to the requested call. A fascinating bug.

shiblu said...

Greetings dear,many many thanks for sharing such wonderful information with us.I am eagerly waiting for your next post.Kindly please visit our site for information about html templates


shiblu said...

I'll give you a pat on the back just for the sheer effort in screencapping all those blogs.Giving a blog talk to beginner bloggers in the not-too-distant future, I'll be pointing people in the direction of your efforts. Nicely put together dude.Here is our small effort about css templates

shiblu said...

Amazing post dude.It will be very helpful for begginers like me.Thank you very much for this important post.Waiting for your next post.You can visit our site to get awesome free plugins