Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

crypto: sha512/arm - fix crash bug in Thumb2 build

The SHA512 code we adopted from the OpenSSL project uses a rather
peculiar way to take the address of the round constant table: it
takes the address of the sha256_block_data_order() routine, and
substracts a constant known quantity to arrive at the base of the
table, which is emitted by the same assembler code right before
the routine's entry point.

However, recent versions of binutils have helpfully changed the
behavior of references emitted via an ADR instruction when running
in Thumb2 mode: it now takes the Thumb execution mode bit into
account, which is bit 0 af the address. This means the produced
table address also has bit 0 set, and so we end up with an address
value pointing 1 byte past the start of the table, which results
in crashes such as

Unable to handle kernel paging request at virtual address bf825000
pgd = 42f44b11
[bf825000] *pgd=80000040206003, *pmd=5f1bd003, *pte=00000000
Internal error: Oops: 207 [#1] PREEMPT SMP THUMB2
Modules linked in: sha256_arm(+) sha1_arm_ce sha1_arm ...
CPU: 7 PID: 396 Comm: cryptomgr_test Not tainted 5.0.0-rc6+ #144
Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
PC is at sha256_block_data_order+0xaaa/0xb30 [sha256_arm]
LR is at __this_module+0x17fd/0xffffe800 [sha256_arm]
pc : [<bf820bca>] lr : [<bf824ffd>] psr: 800b0033
sp : ebc8bbe8 ip : faaabe1c fp : 2fdd3433
r10: 4c5f1692 r9 : e43037df r8 : b04b0a5a
r7 : c369d722 r6 : 39c3693e r5 : 7a013189 r4 : 1580d26b
r3 : 8762a9b0 r2 : eea9c2cd r1 : 3e9ab536 r0 : 1dea4ae7
Flags: Nzcv IRQs on FIQs on Mode SVC_32 ISA Thumb Segment user
Control: 70c5383d Table: 6b8467c0 DAC: dbadc0de
Process cryptomgr_test (pid: 396, stack limit = 0x69e1fe23)
Stack: (0xebc8bbe8 to 0xebc8c000)
...
unwind: Unknown symbol address bf820bca
unwind: Index not found bf820bca
Code: 441a ea80 40f9 440a (f85e) 3b04
---[ end trace e560cce92700ef8a ]---

Given that this affects older kernels as well, in case they are built
with a recent toolchain, apply a minimal backportable fix, which is
to emit another non-code label at the start of the routine, and
reference that instead. (This is similar to the current upstream state
of this file in OpenSSL)

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>

authored by

Ard Biesheuvel and committed by
Herbert Xu
c6431650 69216a54

+4 -2
+2 -1
arch/arm/crypto/sha512-armv4.pl
··· 274 274 .global sha512_block_data_order 275 275 .type sha512_block_data_order,%function 276 276 sha512_block_data_order: 277 + .Lsha512_block_data_order: 277 278 #if __ARM_ARCH__<7 278 279 sub r3,pc,#8 @ sha512_block_data_order 279 280 #else 280 - adr r3,sha512_block_data_order 281 + adr r3,.Lsha512_block_data_order 281 282 #endif 282 283 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) 283 284 ldr r12,.LOPENSSL_armcap
+2 -1
arch/arm/crypto/sha512-core.S_shipped
··· 141 141 .global sha512_block_data_order 142 142 .type sha512_block_data_order,%function 143 143 sha512_block_data_order: 144 + .Lsha512_block_data_order: 144 145 #if __ARM_ARCH__<7 145 146 sub r3,pc,#8 @ sha512_block_data_order 146 147 #else 147 - adr r3,sha512_block_data_order 148 + adr r3,.Lsha512_block_data_order 148 149 #endif 149 150 #if __ARM_MAX_ARCH__>=7 && !defined(__KERNEL__) 150 151 ldr r12,.LOPENSSL_armcap