Skip to content

Commit 6d4a0fb

Browse files
abarnas-usyswilldeacon
authored andcommitted
arm64: Fail module loading if dynamic SCS patching fails
Disallow a module to load if SCS dynamic patching fails for its code. For module loading, instead of running a dry-run to check for patching errors, try to run patching in the first run and propagate any errors so module loading will fail. Signed-off-by: Adrian Barnaś <abarnas@google.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Signed-off-by: Will Deacon <will@kernel.org>
1 parent 7f16357 commit 6d4a0fb

File tree

5 files changed

+19
-9
lines changed

5 files changed

+19
-9
lines changed

arch/arm64/include/asm/scs.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ enum {
5353
EDYNSCS_INVALID_CFA_OPCODE = 4,
5454
};
5555

56-
int __pi_scs_patch(const u8 eh_frame[], int size);
56+
int __pi_scs_patch(const u8 eh_frame[], int size, bool skip_dry_run);
5757

5858
#endif /* __ASSEMBLY __ */
5959

arch/arm64/kernel/module.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -495,10 +495,18 @@ int module_finalize(const Elf_Ehdr *hdr,
495495
if (scs_is_dynamic()) {
496496
s = find_section(hdr, sechdrs, ".init.eh_frame");
497497
if (s) {
498-
ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size);
499-
if (ret)
498+
/*
499+
* Because we can reject modules that are malformed
500+
* so SCS patching fails, skip dry run and try to patch
501+
* it in place. If patching fails, the module would not
502+
* be loaded anyway.
503+
*/
504+
ret = __pi_scs_patch((void *)s->sh_addr, s->sh_size, true);
505+
if (ret) {
500506
pr_err("module %s: error occurred during dynamic SCS patching (%d)\n",
501507
me->name, ret);
508+
return -ENOEXEC;
509+
}
502510
}
503511
}
504512

arch/arm64/kernel/pi/map_kernel.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ static void __init map_kernel(u64 kaslr_offset, u64 va_offset, int root_level)
104104

105105
if (enable_scs) {
106106
scs_patch(__eh_frame_start + va_offset,
107-
__eh_frame_end - __eh_frame_start);
107+
__eh_frame_end - __eh_frame_start, false);
108108
asm("ic ialluis");
109109

110110
dynamic_scs_is_enabled = true;

arch/arm64/kernel/pi/patch-scs.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ static int scs_handle_fde_frame(const struct eh_frame *frame,
225225
return 0;
226226
}
227227

228-
int scs_patch(const u8 eh_frame[], int size)
228+
int scs_patch(const u8 eh_frame[], int size, bool skip_dry_run)
229229
{
230230
int code_alignment_factor = 1;
231231
bool fde_use_sdata8 = false;
@@ -277,11 +277,13 @@ int scs_patch(const u8 eh_frame[], int size)
277277
}
278278
} else {
279279
ret = scs_handle_fde_frame(frame, code_alignment_factor,
280-
fde_use_sdata8, true);
280+
fde_use_sdata8, !skip_dry_run);
281281
if (ret)
282282
return ret;
283-
scs_handle_fde_frame(frame, code_alignment_factor,
284-
fde_use_sdata8, false);
283+
284+
if (!skip_dry_run)
285+
scs_handle_fde_frame(frame, code_alignment_factor,
286+
fde_use_sdata8, false);
285287
}
286288

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

arch/arm64/kernel/pi/pi.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ extern pgd_t init_pg_dir[], init_pg_end[];
2727
void init_feature_override(u64 boot_status, const void *fdt, int chosen);
2828
u64 kaslr_early_init(void *fdt, int chosen);
2929
void relocate_kernel(u64 offset);
30-
int scs_patch(const u8 eh_frame[], int size);
30+
int scs_patch(const u8 eh_frame[], int size, bool skip_dry_run);
3131

3232
void map_range(phys_addr_t *pte, u64 start, u64 end, phys_addr_t pa,
3333
pgprot_t prot, int level, pte_t *tbl, bool may_use_cont,

0 commit comments

Comments
 (0)