Skip to content
This repository has been archived by the owner on Mar 24, 2021. It is now read-only.

Fix ret2spec demo so it doesn't segfault without optimizations #26

Open
mmdriley opened this issue Oct 2, 2019 · 5 comments
Open

Fix ret2spec demo so it doesn't segfault without optimizations #26

mmdriley opened this issue Oct 2, 2019 · 5 comments

Comments

@mmdriley
Copy link
Member

mmdriley commented Oct 2, 2019

Current behavior if the example is compiled at -O0:

Starting program: .../safeside/ret2spec 
Leaking the string: 
Program received signal SIGSEGV, Segmentation fault.
0x0000000000404b2c in ForceRead(void const*) ()
(gdb) bt
#0  0x0000000000404b2c in ForceRead(void const*) ()
#1  0x000000000040216e in CacheSideChannel::AddHitAndRecomputeScores() ()
#2  0x0000000000401445 in leak_byte() ()
#3  0x0000000000000000 in ?? ()
(gdb) disas
Dump of assembler code for function _Z9ForceReadPKv:
   0x0000000000404b20 <+0>:	push   %rbp
   0x0000000000404b21 <+1>:	mov    %rsp,%rbp
   0x0000000000404b24 <+4>:	mov    %rdi,-0x8(%rbp)
   0x0000000000404b28 <+8>:	mov    -0x8(%rbp),%rdi
=> 0x0000000000404b2c <+12>:	mov    (%rdi),%al
   0x0000000000404b2e <+14>:	mov    %al,-0x9(%rbp)
   0x0000000000404b31 <+17>:	pop    %rbp
   0x0000000000404b32 <+18>:	retq   
End of assembler dump.
(gdb) info reg rdi
rdi            0x80000000bae8      140737488403176

I think it's okay if the example doesn't work below -O2, but we should improve it so it at least doesn't crash.

@asteinha
Copy link
Contributor

asteinha commented Oct 2, 2019

It works also with -O1 or even just with -fomit-frame-pointer.

@asteinha
Copy link
Contributor

asteinha commented Oct 2, 2019

The issue is that -O0 by default uses rbp (or ebp) for addressing the stack variables instead of rsp (or esp). Ebp is pushed on the stack on prologue of each function and restored in its epilogue, because it's a callee-saved register by the calling-convention. By unrolling the stack to create the RSB mismatch I'm destroying its value misdirecting all following stack accesses. It is possible to detect it just creating two functions that do nothing and observing whether the value of rbp changed across them.

@mmdriley
Copy link
Member Author

mmdriley commented Oct 2, 2019

It does work with -O1, but oddly I found that compiling all files with just -fomit-frame-pointer did not work for Clang or GCC. Maybe that can only apply when any optimizations are enabled?

@asteinha
Copy link
Contributor

asteinha commented Oct 2, 2019

I'll look at this eventually. That's unexpected.

@asteinha
Copy link
Contributor

asteinha commented Oct 3, 2019

There are at least two problems:

  1. pollution of the rbp register - that can be solved relatively easily by replacing the addq $8, %%rsp with popq %%rbp, because the last value before the return address is the rbp backup.
  2. Having the address argument on the stack instead of a register - than the UnwindStack matches that argument instead of the return address and does not unroll the stack sufficiently.
    I'll probably write a helper method which finds out whether the rbp is used as a frame pointer. Then I can store the return address mangled (e.g. shifted by 1), so that it is not falsely matched.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants