mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-17 10:04:26 +00:00
fix: backtrace stack unwind misses lr adjustment
When pointer authentication is used the frame record return address includes the pointer authentication code hence it must be masked out when willing to compare the pointer value with another address or checking its validity. The stack unwind function missed one case of adjusting the return address leading to a misinterpreted corrupted stack frame error message. Signed-off-by: Olivier Deprez <olivier.deprez@arm.com> Change-Id: I435140937d5fd0f43da27c77d96056b7606d87e9
This commit is contained in:
parent
c19116dd61
commit
a149eb4d87
1 changed files with 24 additions and 20 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved.
|
||||
* Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
@ -37,6 +37,23 @@ struct frame_record {
|
|||
uintptr_t return_addr;
|
||||
};
|
||||
|
||||
static inline uintptr_t extract_address(uintptr_t address)
|
||||
{
|
||||
uintptr_t ret = address;
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/*
|
||||
* When pointer authentication is enabled, the LR value saved on the
|
||||
* stack contains a PAC. It must be stripped to retrieve the return
|
||||
* address.
|
||||
*/
|
||||
|
||||
xpaci(ret);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *get_el_str(unsigned int el)
|
||||
{
|
||||
if (el == 3U) {
|
||||
|
@ -53,18 +70,11 @@ const char *get_el_str(unsigned int el)
|
|||
* the current EL, false otherwise.
|
||||
*/
|
||||
#ifdef __aarch64__
|
||||
static bool is_address_readable(uintptr_t addr)
|
||||
static bool is_address_readable(uintptr_t address)
|
||||
{
|
||||
unsigned int el = get_current_el();
|
||||
uintptr_t addr = extract_address(address);
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/*
|
||||
* When pointer authentication is enabled, the LR value saved on the
|
||||
* stack contains a PAC. It must be stripped to retrieve the return
|
||||
* address.
|
||||
*/
|
||||
xpaci(addr);
|
||||
#endif
|
||||
if (el == 3U) {
|
||||
ats1e3r(addr);
|
||||
} else if (el == 2U) {
|
||||
|
@ -185,7 +195,8 @@ static void unwind_stack(struct frame_record *fr, uintptr_t current_pc,
|
|||
return;
|
||||
}
|
||||
|
||||
if (fr->return_addr != link_register) {
|
||||
call_site = extract_address(fr->return_addr);
|
||||
if (call_site != link_register) {
|
||||
printf("ERROR: Corrupted stack (frame record address = %p)\n",
|
||||
fr);
|
||||
return;
|
||||
|
@ -207,16 +218,9 @@ static void unwind_stack(struct frame_record *fr, uintptr_t current_pc,
|
|||
* call was made is the instruction before the return address,
|
||||
* which is always 4 bytes before it.
|
||||
*/
|
||||
call_site = fr->return_addr - 4U;
|
||||
|
||||
#if ENABLE_PAUTH
|
||||
/*
|
||||
* When pointer authentication is enabled, the LR value saved on
|
||||
* the stack contains a PAC. It must be stripped to retrieve the
|
||||
* return address.
|
||||
*/
|
||||
xpaci(call_site);
|
||||
#endif
|
||||
call_site = extract_address(fr->return_addr) - 4U;
|
||||
|
||||
/*
|
||||
* If the address is invalid it means that the frame record is
|
||||
* probably corrupted.
|
||||
|
|
Loading…
Add table
Reference in a new issue