gdb: Enable displaced stepping with shadow stack on amd64 linux.

Currently, if displaced stepping is active and the single stepped instruction
is a call instruction, the return address atop the stack is the address
following the copied instruction.  However, to allow normal program execution
it has to be the address following the original instruction.  Due to that
reason, the return address is corrected in amd64_displaced_step_fixup and
i386_displaced_step_fixup.

For programs that are shadow-stack enabled we see a control-protection
exception, as the address on the shadow stack does not match the address
atop the stack.

Fix this by correcting the shadow stack top address as well.

Approved-By: Andrew Burgess <aburgess@redhat.com>
Approved-By: Luis Machado <luis.machado@arm.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
This commit is contained in:
Christina Schimpe
2022-02-18 03:09:46 -08:00
parent 66dee5a4f0
commit 7a8821ff0e
7 changed files with 150 additions and 3 deletions

View File

@@ -1939,8 +1939,10 @@ amd64_linux_shadow_stack_element_size_aligned (gdbarch *gdbarch)
possible. */
static std::optional<CORE_ADDR>
amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache)
amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache,
bool &shadow_stack_enabled)
{
shadow_stack_enabled = false;
const i386_gdbarch_tdep *tdep = gdbarch_tdep<i386_gdbarch_tdep> (gdbarch);
if (tdep->ssp_regnum < 0)
@@ -1958,6 +1960,9 @@ amd64_linux_get_shadow_stack_pointer (gdbarch *gdbarch, regcache *regcache)
if (ssp == 0x0)
return {};
/* In case there is a shadow stack pointer available which is non-null,
the shadow stack feature is enabled. */
shadow_stack_enabled = true;
return ssp;
}
@@ -1968,10 +1973,17 @@ static void
amd64_linux_shadow_stack_push (gdbarch *gdbarch, CORE_ADDR new_addr,
regcache *regcache)
{
bool shadow_stack_enabled;
std::optional<CORE_ADDR> ssp
= amd64_linux_get_shadow_stack_pointer (gdbarch, regcache);
= amd64_linux_get_shadow_stack_pointer (gdbarch, regcache,
shadow_stack_enabled);
/* For amd64/Linux, if SSP has a value that means shadow stack is
enabled. */
if (!ssp.has_value ())
return;
else
gdb_assert (shadow_stack_enabled);
/* The shadow stack grows downwards. To push addresses to the stack,
we need to decrement SSP. */
@@ -2126,6 +2138,8 @@ amd64_linux_init_abi_common (struct gdbarch_info info, struct gdbarch *gdbarch,
(gdbarch, amd64_linux_remove_non_address_bits_watchpoint);
set_gdbarch_shadow_stack_push (gdbarch, amd64_linux_shadow_stack_push);
set_gdbarch_get_shadow_stack_pointer (gdbarch,
amd64_linux_get_shadow_stack_pointer);
dwarf2_frame_set_init_reg (gdbarch, amd64_init_reg);
}