Skip to content

Commit 54c968b

Browse files
ardbiesheuvelctmarinas
authored andcommitted
arm64: Apply dynamic shadow call stack patching in two passes
Code patching for the dynamically enabled shadow call stack comes down to finding PACIASP and AUTIASP instructions -which behave as NOPs on cores that do not implement pointer authentication- and converting them into shadow call stack pushes and pops, respectively. Due to past bad experiences with the highly complex and overengineered DWARF standard that describes the unwind metadata that we are using to locate these instructions, let's make this patching logic a little bit more robust so that any issues with the unwind metadata detected at boot time can de dealt with gracefully. The DWARF annotations that are used for this are emitted at function granularity, and due to the fact that the instructions we are patching will simply behave as NOPs if left unpatched, we can abort on errors as long as we don't leave any functions in a half-patched state. So do a dry run of each FDE frame (covering a single function) before performing the actual patching, and give up if the DWARF metadata cannot be understood. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Will Deacon <will@kernel.org> Reviewed-by: Sami Tolvanen <samitolvanen@google.com> Link: https://lore.kernel.org/r/20221213142849.1629026-1-ardb@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
1 parent bb457bd commit 54c968b

1 file changed

Lines changed: 8 additions & 3 deletions

File tree

arch/arm64/kernel/patch-scs.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ struct eh_frame {
130130

131131
static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
132132
bool fde_has_augmentation_data,
133-
int code_alignment_factor)
133+
int code_alignment_factor,
134+
bool dry_run)
134135
{
135136
int size = frame->size - offsetof(struct eh_frame, opcodes) + 4;
136137
u64 loc = (u64)offset_to_ptr(&frame->initial_loc);
@@ -184,7 +185,8 @@ static int noinstr scs_handle_fde_frame(const struct eh_frame *frame,
184185
break;
185186

186187
case DW_CFA_negate_ra_state:
187-
scs_patch_loc(loc - 4);
188+
if (!dry_run)
189+
scs_patch_loc(loc - 4);
188190
break;
189191

190192
case 0x40 ... 0x7f:
@@ -235,9 +237,12 @@ int noinstr scs_patch(const u8 eh_frame[], int size)
235237
} else {
236238
ret = scs_handle_fde_frame(frame,
237239
fde_has_augmentation_data,
238-
code_alignment_factor);
240+
code_alignment_factor,
241+
true);
239242
if (ret)
240243
return ret;
244+
scs_handle_fde_frame(frame, fde_has_augmentation_data,
245+
code_alignment_factor, false);
241246
}
242247

243248
p += sizeof(frame->size) + frame->size;

0 commit comments

Comments
 (0)