Received: by 2002:a05:6a10:eb17:0:0:0:0 with SMTP id hx23csp743435pxb; Wed, 8 Sep 2021 11:13:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzQTUrzWfM0L3PCOMiXH5fio3ug4zzb5GQnIJrlNQHvlsgWyF3AWbok3AURJ/XD3wjvtLCF X-Received: by 2002:a5d:9c53:: with SMTP id 19mr964594iof.192.1631124783692; Wed, 08 Sep 2021 11:13:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631124783; cv=none; d=google.com; s=arc-20160816; b=HCZ1QguS+LgcN3C42V3wWZ8YVdGe7LUV161frV7a+qAcFrQHR5bxIVlZcWwekaPcAJ BXweo69vzosDqAHP4fHwOksA8r3i4fnVHzdwMVQk2FKtTA+Odb2gz/D6VFUk/opNEDoO dKf9QOeb+ZA9J6sM6QsuSHh5PP73Vg6gHeh4sKGx/Z6ViSby0URVqdIa2SUdDYzruHs1 DMYD7BDdn+AyBx7XHdSIvEjBGYL5A4frM+8paKPJl9SrCxirY6iNSsVCsq+eSGn5gRZd KbAf3pa3DqXmXVmlWDiHHIsmzgIJncZhvmNVz+S3uqAtyGGU3o092ZYknsnHq8PASVWl eTrQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:message-id:date:subject:cc:to:from; bh=DkzdTO75khRuI2MJa4tSksdR/zvqLfgU6TwXnbtDgik=; b=qoh23kqzlS/X7sZoT/ip1/ELBwfJhZ+ZjxEOHXR1vemsW5zb0SGav7FbmXXOfiVjsp 1Tn7Ihxr/FXePxXpyFzm3vw7ua9rA/yDE+zwj6pPxqJNtIoapub51oIKDrWKbe9tHTvA 4F7VJ4axhJ03tixtmUy2hAdp5bPGW5g2vUlPBpvntMAIY+9KIyADHRjXddhM68JImzjf mJGbvsDN2VNy3/H+Jc9yDIZ0LkjU1xXGCXWgPYE9SjisgNT+VhsSqOHUfZtoqhlDCjRe WxuI2zc+qVH7HqGH9v1aSPs8S7gN4ANWwQqTBSejVczyFlILM4HLtX8tabFub+d03thn zP2g== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t44si2761971jal.14.2021.09.08.11.12.51; Wed, 08 Sep 2021 11:13:03 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1348529AbhIHQ1d (ORCPT + 99 others); Wed, 8 Sep 2021 12:27:33 -0400 Received: from foss.arm.com ([217.140.110.172]:48646 "EHLO foss.arm.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238352AbhIHQ1c (ORCPT ); Wed, 8 Sep 2021 12:27:32 -0400 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 64B231FB; Wed, 8 Sep 2021 09:26:24 -0700 (PDT) Received: from donnerap.arm.com (donnerap.cambridge.arm.com [10.1.197.93]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 108923F766; Wed, 8 Sep 2021 09:26:22 -0700 (PDT) From: Andre Przywara To: Russell King , Ard Biesheuvel Cc: linux-efi@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Linus Walleij , Catalin Marinas , Adam Lackorzynski , Peter Maydell Subject: [PATCH] ARM: decompressor: Avoid UNPREDICTABLE NOP encoding Date: Wed, 8 Sep 2021 17:26:17 +0100 Message-Id: <20210908162617.104962-1-andre.przywara@arm.com> X-Mailer: git-send-email 2.17.1 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org In the decompressor's head.S we need to start with an instruction that is some kind of NOP, but also mimics as the PE/COFF header, when the kernel is linked as an UEFI application. The clever solution here is "tstne r0, #0x4d000", which in the worst case just clobbers the condition flags, and bears the magic "MZ" signature in the lowest 16 bits. However the encoding used (0x13105a4d) is actually not valid, since bits [15:12] are supposed to be 0 (written as "(0)" in the ARM ARM). Violating this is UNPREDICTABLE, and *can* trigger an UNDEFINED exception. Common Cortex cores seem to ignore those bits, but QEMU chooses to trap, so the code goes fishing because of a missing exception handler at this point. We are just saved by the fact that commonly (with -kernel or when running from U-Boot) the "Z" bit is set, so the instruction is never executed. See [0] for more details. To make things more robust and avoid UNPREDICTABLE behaviour in the kernel code, lets replace this with a "two-instruction NOP": The first instruction is an exclusive OR, the effect of which the second instruction reverts. This does not leave any trace, neither in a register nor in the condition flags. Also it's a perfectly valid encoding. Kudos to Peter Maydell for coming up with this gem. [0] https://lore.kernel.org/qemu-devel/YTPIdbUCmwagL5%2FD@os.inf.tu-dresden.de/T/ Signed-off-by: Andre Przywara Reported-by: Adam Lackorzynski Suggested-by: Peter Maydell --- arch/arm/boot/compressed/efi-header.S | 22 ++++++++++++++-------- arch/arm/boot/compressed/head.S | 3 ++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/arch/arm/boot/compressed/efi-header.S b/arch/arm/boot/compressed/efi-header.S index c0e7a745103e..230030c13085 100644 --- a/arch/arm/boot/compressed/efi-header.S +++ b/arch/arm/boot/compressed/efi-header.S @@ -9,16 +9,22 @@ #include .macro __nop -#ifdef CONFIG_EFI_STUB - @ This is almost but not quite a NOP, since it does clobber the - @ condition flags. But it is the best we can do for EFI, since - @ PE/COFF expects the magic string "MZ" at offset 0, while the - @ ARM/Linux boot protocol expects an executable instruction - @ there. - .inst MZ_MAGIC | (0x1310 << 16) @ tstne r0, #0x4d000 -#else AR_CLASS( mov r0, r0 ) M_CLASS( nop.w ) + .endm + + .macro __initial_nops +#ifdef CONFIG_EFI_STUB + @ This is a two-instruction NOP, which happens to bear the + @ PE/COFF signature "MZ" in the first two bytes, so the kernel + @ is accepted as an EFI binary. Booting via the UEFI stub + @ will not execute those instructions, but the ARM/Linux + @ boot protocol does, so we need some NOPs here. + .inst MZ_MAGIC | (0xe225 << 16) @ eor r5, r5, 0x4d000 + eor r5, r5, 0x4d000 @ undo previous insn +#else + __nop + __nop #endif .endm diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index b1cb1972361b..bf79f2f78d23 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -203,7 +203,8 @@ start: * were patching the initial instructions of the kernel, i.e * had started to exploit this "patch area". */ - .rept 7 + __initial_nops + .rept 5 __nop .endr #ifndef CONFIG_THUMB2_KERNEL -- 2.17.1