From 65d457fae42006f2797857e7ae0ceab8e9650613 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 8 Mar 2024 23:24:00 +0000 Subject: [PATCH] ANDROID: fips140 - fix integrity check by unapplying dynamic SCS Since the kernel now has dynamic Shadow Call Stack (SCS) enabled, on CPUs that don't support Pointer Authentication Codes (PAC) the kernel runtime-patches paciasp and autiasp instructions into instructions that push and pop from the shadow call stack. This includes instructions in loaded modules. This broke the fips140 integrity check which needs to know how to undo all text changes made by the module loader in order to re-create the original text. Fix this by updating fips140.ko to undo the dynamic SCS patching. Bug: 188620248 Change-Id: I992bcd6c34b3340c6489b40a125715e1304cb445 Signed-off-by: Eric Biggers --- crypto/fips140-module.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crypto/fips140-module.c b/crypto/fips140-module.c index 5969a57dbb73..3886b3cce62b 100644 --- a/crypto/fips140-module.c +++ b/crypto/fips140-module.c @@ -358,6 +358,33 @@ static void __init unapply_rodata_relocations(void *section, int section_size, } } +enum { + PACIASP = 0xd503233f, + AUTIASP = 0xd50323bf, + SCS_PUSH = 0xf800865e, + SCS_POP = 0xf85f8e5e, +}; + +/* + * To make the integrity check work with dynamic Shadow Call Stack (SCS), + * replace all instructions that push or pop from the SCS with the Pointer + * Authentication Code (PAC) instructions that were present originally. + */ +static void __init unapply_scs_patch(void *section, int section_size) +{ +#if defined(CONFIG_ARM64) && defined(CONFIG_UNWIND_PATCH_PAC_INTO_SCS) + u32 *insns = section; + int i; + + for (i = 0; i < section_size / sizeof(insns[0]); i++) { + if (insns[i] == SCS_PUSH) + insns[i] = PACIASP; + else if (insns[i] == SCS_POP) + insns[i] = AUTIASP; + } +#endif +} + #ifdef CONFIG_CRYPTO_FIPS140_MOD_DEBUG_INTEGRITY_CHECK static struct { const void *text; @@ -460,6 +487,8 @@ static bool __init check_fips140_module_hmac(void) offset_to_ptr(&fips140_rela_rodata.offset), fips140_rela_rodata.count); + unapply_scs_patch(textcopy, textsize); + fips140_init_integrity_debug_files(textcopy, textsize, rodatacopy, rodatasize);