From patchwork Mon Oct 18 14:16:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 12566607 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 412AEC433F5 for ; Mon, 18 Oct 2021 14:23:07 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 0C24360F46 for ; Mon, 18 Oct 2021 14:23:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 0C24360F46 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=8PxJMuzVDh2Db7k+kZ1Yg3ulTHqExrf8MPqljA8uqG8=; b=q24PQ3E3HiKlCt hCRmd5rUU1Q9eESsc0C1FUbz5hvuWQNu0IjuvtBa0WVZ9r4NCQCY/+sFG2/KIvy22TzEfYAgfgq4p Sag1AflqdsFWdOT/R+aB+vySxkmfZLWHF/FTjHyxKUfp6RGIgGg92qoCNDgSWQeS2ZaehQ7tQSGBd oa8OB+7oR3+lXZE6qH+HarpgknSRZVhMqEyXr70ebC7xaXtRuFk88XqDftRUlt4K7PbD7ykTirzKD GxAcc+fR1MCNBsD/580dWwzItySd+/coGQL/CRPR3Tq06esuX6NDqmarvBvbwwucHloyd8SZ2a4v3 jZy6uR3rYFK+h13gvk+Q==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1mcTW7-00G4fU-KC; Mon, 18 Oct 2021 14:21:32 +0000 Received: from mail.kernel.org ([198.145.29.99]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1mcTRQ-00G2nN-Sn for linux-arm-kernel@lists.infradead.org; Mon, 18 Oct 2021 14:16:42 +0000 Received: by mail.kernel.org (Postfix) with ESMTPSA id C4B6060FC2; Mon, 18 Oct 2021 14:16:37 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1634566599; bh=G8bl/jS0UF4ofWVfxX1cIJJ06WAI6ETjTnMacIEZcB4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XaQB3J0Muivcn8tTtUal0wmVFqC31pC2+mJob5CK1u/SJae5qRskK+s4pManjFUc9 euqSE0DSGqpuLIDKfuQWO5o4vICnel6SjVsv2JTfM81F5e5QYOBxEpl5t6WVhW3OXo CyuwUhU+6JSzsJb41YlsVuwxRjRtDPSBg0VbozJZ/YN17DZGBuokpuhFo8xAfKWDzm K5WMTVKAwQ1qUrSsfHwOqlpcbYBhd4HYtXyx/tOhQJDrzwJJeyJ7+a6aM32q2Z2gFS qRb7jHHMK8VX6dXVs21xvjCjf5EcV2fUd4moRhzyDlOu5GjiBzechMGVvU1ba86xaW nf6Zwi37d+eOg== From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org Cc: Ard Biesheuvel , Russell King , Nicolas Pitre , Arnd Bergmann , Kees Cook , Keith Packard , Linus Walleij , Nick Desaulniers Subject: [PATCH v2 4/7] ARM: unwind: disregard unwind info before stack frame is set up Date: Mon, 18 Oct 2021 16:16:12 +0200 Message-Id: <20211018141615.682070-5-ardb@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20211018141615.682070-1-ardb@kernel.org> References: <20211018141615.682070-1-ardb@kernel.org> MIME-Version: 1.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=2389; h=from:subject; bh=G8bl/jS0UF4ofWVfxX1cIJJ06WAI6ETjTnMacIEZcB4=; b=owEB7QES/pANAwAKAcNPIjmS2Y8kAcsmYgBhbYGouEi30aIbAnRchjXXGvZ89mMKIIQd149EMa+6 bmr6GyKJAbMEAAEKAB0WIQT72WJ8QGnJQhU3VynDTyI5ktmPJAUCYW2BqAAKCRDDTyI5ktmPJN2pDA CLfK7SOKZkG1fABk1of33RE/+72XRuljrWH9LMMpycdxO40B0SBMbFnmpthb4dmTu/eNriSUBHGOub VRMg/x8yLKvLSaZ4z/6dhWCAJfJ+YBjPBfREJYHwarPtxF76QZjbgKZDRoIRUYlAR459hAXNALHV/0 H31c0oRzZxeYhOlWtydj17vnGitz40PSHejCn70NiPW3/qrfREfaqfIEUIONdy44oqyw58eQUFfdR6 G1Z1qcqzJHi9y0K9jIc56CL6oeWf4pwsvtnCT5M6h2t+RLYOQhvygbWHgNYYna7lHzE1UpE4yr0oV5 wm9JBlNM2n/iRLudjhw4GQoFYO/V1fXwdmFuKLSZ08GjwcTD8MjzXpj5+F//GJgSLk5OkvAmD139ck uK+ap1K2UdNhqfRCVbdMzINLeF1IMW2ZdiZCJRhLUmbqbqlZ8RtScMlINk0WWUMjnDUWbzCqxCp5v0 4EF26fGygnb0QSO7u7wMtORx9hn8Vlc4SN0oK0ZT+0ewU= X-Developer-Key: i=ardb@kernel.org; a=openpgp; fpr=F43D03328115A198C90016883D200E9CA6329909 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20211018_071641_071445_C0E208BF X-CRM114-Status: GOOD ( 18.59 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org When unwinding the stack from a stack overflow, we are likely to start from a stack push instruction, given that this is the most common way to grow the stack for compiler emitted code. This push instruction rarely appears anywhere else than at offset 0x0 of the function, and if it doesn't, the compiler tends to split up the unwind annotations, given that the stack frame layout is apparently not the same throughout the function. This means that, in the general case, if the frame's PC points at the first instruction covered by a certain unwind entry, there is no way the stack frame that the unwind entry describes could have been created yet, and so we are still on the stack frame of the caller in that case. So treat this as a special case, and return with the new PC taken from the frame's LR, without applying the unwind transformations to the virtual register set. This permits us to unwind the call stack on stack overflow when the overflow was caused by a stack push on function entry. Signed-off-by: Ard Biesheuvel Tested-by: Keith Packard --- arch/arm/kernel/unwind.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index b7a6141c342f..e8d729975f12 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c @@ -411,7 +411,21 @@ int unwind_frame(struct stackframe *frame) if (idx->insn == 1) /* can't unwind */ return -URC_FAILURE; - else if ((idx->insn & 0x80000000) == 0) + else if (frame->pc == prel31_to_addr(&idx->addr_offset)) { + /* + * Unwinding is tricky when we're halfway through the prologue, + * since the stack frame that the unwinder expects may not be + * fully set up yet. However, one thing we do know for sure is + * that if we are unwinding from the very first instruction of + * a function, we are still effectively in the stack frame of + * the caller, and the unwind info has no relevance yet. + */ + if (frame->pc == frame->lr) + return -URC_FAILURE; + frame->sp_low = frame->sp; + frame->pc = frame->lr; + return URC_OK; + } else if ((idx->insn & 0x80000000) == 0) /* prel31 to the unwind table */ ctrl.insn = (unsigned long *)prel31_to_addr(&idx->insn); else if ((idx->insn & 0xff000000) == 0x80000000)