Incorrect stack alignment on x86-64
See original GitHub issueI’m trying to get my rust binary running under angr
for symbolic execution. I’ve pared it down to, well, nothing:
#![feature(alloc_system, global_allocator, allocator_api)]
extern crate alloc_system;
use alloc_system::System;
#[global_allocator]
static A: System = System;
fn main() {
return;
}
(We use the system allocator here instead of jemalloc
, Rust’s default, to avoid having to patch out a bunch of syscalls.)
You can build this binary by starting a new crate with cargo init --bin
and using that as the src/main.rs
file. LMK if you’d like more detail for building the rust side, of course. (Or I can send you a binary.)
Then, I’m running this script inside the angr/angr
docker container:
import angr
def main(p):
proj = angr.Project(
p,
use_sim_procedures=True,
translation_cache=True,
support_selfmodifying_code=False,
)
# No-op the signal handler installation (for now)
class signal(angr.SimProcedure):
def run(self, *args, **kwargs):
return 0
proj.hook_symbol('signal', signal())
opts = {
angr.options.ZERO_FILL_UNCONSTRAINED_MEMORY,
angr.options.STRICT_PAGE_ACCESS,
angr.options.UNICORN,
}
entry_state = proj.factory.entry_state(
add_options=opts,
args={},
env={},
)
simulation_manager = angr.SimulationManager(
project=proj,
active_states=[entry_state],
)
i = 0
while len(simulation_manager.active) == 1 and not simulation_manager.errored:
simulation_manager.step()
i += 1
if simulation_manager.active:
print("Stopped with %d states!" % len(simulation_manager.active))
actions = list(simulation_manager.active[0].history.actions)
print actions[-1]
elif simulation_manager.errored:
errored = simulation_manager.errored[0]
print("Errored: %s" % (errored.error,))
state = errored.state
print("rip: %s" % (state.regs.rip))
print("rsp: %s" % (state.regs.rsp))
print("rbp: %s" % (state.regs.rbp))
proj.factory.block(state.solver.eval(state.regs.rip)).pp()
print("")
for frame in state.callstack:
try:
name = proj.kb.labels.get(frame.current_function_address)
except KeyError:
name = None
print(">> %s" % (name,))
print("")
import ipdb; ipdb.set_trace()
The program steps through until…
Errored: Cannot execute following jumpkind Ijk_SigSEGV
rip: <BV64 0x407f54>
rsp: <BV64 0x7fffffffffefdb8>
rbp: <BV64 0x7fffffffffefe98>
0x407f54: movaps xmmword ptr [rbp - 0xc0], xmm0
0x407f5b: movaps xmmword ptr [rbp - 0xd0], xmm0
0x407f62: movaps xmmword ptr [rbp - 0xe0], xmm0
0x407f69: mov qword ptr [rbp - 0xb0], 0
0x407f74: lea rdi, [rbp - 0xe0]
0x407f7b: call 0x4032c0
>> _ZN3std3sys4unix6thread5guard4init17ha4e308f7b00e4ed6E
>> _ZN3std2rt19lang_start_internal17hd640de3aab7bd269E
>> main
>> __libc_start_main
>> None
Note that rbp
is not 16 byte aligned, so the movaps
is going to fail with a protection fault.
If I run the same program directly, it works, and if I break at the offending instruction in gdb
, rbp
is indeed 16 byte aligned.
Configuration
$ uname -a
Linux sujayakar-vm 4.4.0-119-generic #143-Ubuntu SMP Mon Apr 2 16:08:24 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
$ rustc --version
rustc 1.27.0-nightly (79252ff4e 2018-04-29)
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (4 by maintainers)
Top GitHub Comments
Hi, digging this up since I’ve stumbled upon the same problem. I believe the issue is in the implementation of
__libc_start_main
, where it says:Reading the document (which now lives at https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf), it says
I believe the key phrase here is “when control is transferred to the function entry point”, which I read as “after the
call
instruction”. However, in angr’s__libc_start_main
abstraction, the alignment is made before the return pointer is placed onto the stack. Thus, when the control is transferred to the function entry point, alignment is off by 8.Does this seem plausible? If so I’m happy to provide a pull request.
Interesting. I would call this plausible indeed. If it fixes something for you, we’d be happy to take it as a PR.