From patchwork Fri Oct 5 08:13:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 10627601 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B77521515 for ; Fri, 5 Oct 2018 08:17:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id AF4AE29295 for ; Fri, 5 Oct 2018 08:17:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id A063F29280; Fri, 5 Oct 2018 08:17:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 493B02929B for ; Fri, 5 Oct 2018 08:17:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:References: In-Reply-To:Message-Id:Date:Subject:To:From:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Owner; bh=+4nlXDVC2yVMfxC60fNWLcviZlET2xtX/Z2zobA0g60=; b=FkTUMmCxPN/GcZj9t5ozEeVrZV qzwnNYQ1uqeTq7mRTm//lLq9Dx7OQE56gyc4ctXJbZpdVGTv6HOpQev+pqezXmqfqqrxnePOHuQ5P 4qVOHWxz6SbiUvbQqT6UbYOBrP7vQ4JHRCrKIFiz+VqaZPjAaiooB8Nbs7Y281JVKE4H9C6Zvgfk7 OcXN4cnzs+fdp/rYKv6tla0+tbTV2s2BFRlKalUG9ocXNFFyMBZy7kqLEVOJL9AupXEk//LJl0V+L 9ZAbP3lKTxTszKSL3Lwr9IgLAHpI1+U5bYlqt22NAEhYjGjIwNV/SZbjARJObjitivH72MslI4BMT QinFiXXA==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1g8LI6-0007dd-OE; Fri, 05 Oct 2018 08:16:54 +0000 Received: from mail-wm1-x344.google.com ([2a00:1450:4864:20::344]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1g8LFB-0004xV-HH for linux-arm-kernel@lists.infradead.org; Fri, 05 Oct 2018 08:14:04 +0000 Received: by mail-wm1-x344.google.com with SMTP id 143-v6so983091wmf.1 for ; Fri, 05 Oct 2018 01:13:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Bsz7BDS1SKX9gHYXcW+7Yci+Ue2vSEITfG0cme0MbDA=; b=kI1I9XaciHUjWQntHHKbdAEv8Lm6aYT5IbNk7lfmiPNfZV7PrVjSNpmFq2Jb0VlwbE ZuX3XeBgMPpPy+wOgvVxMR/QHwgKKUOYnCADUKvUpr9aZKOY7+D76TJkI/VCLKkKNez8 +gmvc8uxFGNprC67bkbat2uDXwlxiRbel6D0c= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Bsz7BDS1SKX9gHYXcW+7Yci+Ue2vSEITfG0cme0MbDA=; b=jD3gTEp6+0QopSVomXe92N6zMUW3dWYTvfaQECuL6msio3AX5yu3DZCd7qL0dSMr3Y tZUhYCalccKKdZrUoHdyaAUNp2nkx77TnWfKHnWxbvwxPK8pPBd1qYMwPsWuOBbZ48Ka pOoOXWs1zsEjxMR0dji5AVIGzJntBuiG3zIJSoJGPqz58c0ex3SNCx98ypcAJMBjuuef 72LR+NSObGeHOhdBGE1i5FiPQp9jBLNh65sZBxWst6wmvq9/TW6tZjL2QmsQThxfAzcj eO3GvoMz5ySdzeG9FiiPskRaCHXVVkmqVu+eEncSSeqDjiMXu8bxhBvgyoqGN4BwRc03 /mrA== X-Gm-Message-State: ABuFfojXe92lKuutRwjyqNOG2jSfbF5Annb+4PEl5u9S7gVgJxxaQxWe 5Y8a46YY5IopYw5Fvao/LF2y9Q== X-Google-Smtp-Source: ACcGV62etp+lM1HN/t1sYejJBWMbHx2UjdBHB+cI2jGegnJnCQHI4XozZ0fBzC1R8f1Ib4p8VBAR+g== X-Received: by 2002:a1c:14d1:: with SMTP id 200-v6mr7367930wmu.106.1538727221719; Fri, 05 Oct 2018 01:13:41 -0700 (PDT) Received: from localhost.localdomain ([2a01:cb1d:112:6f00:697e:67d9:a05d:22c7]) by smtp.gmail.com with ESMTPSA id t4-v6sm6565620wrb.45.2018.10.05.01.13.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 05 Oct 2018 01:13:40 -0700 (PDT) From: Ard Biesheuvel To: linux-kernel@vger.kernel.org Subject: [RFC PATCH 2/9] arm64: kernel: add arch support for patchable function pointers Date: Fri, 5 Oct 2018 10:13:26 +0200 Message-Id: <20181005081333.15018-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20181005081333.15018-1-ard.biesheuvel@linaro.org> References: <20181005081333.15018-1-ard.biesheuvel@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181005_011353_612678_8ECD2813 X-CRM114-Status: GOOD ( 19.10 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: "Jason A . Donenfeld" , Peter Zijlstra , Catalin Marinas , Will Deacon , Samuel Neves , Paul Mackerras , Herbert Xu , Richard Weinberger , Eric Biggers , Ingo Molnar , Benjamin Herrenschmidt , Kees Cook , Arnd Bergmann , Andy Lutomirski , Thomas Gleixner , linux-arm-kernel@lists.infradead.org, "Martin K. Petersen" , Ard Biesheuvel , Greg Kroah-Hartman , linux-crypto@vger.kernel.org, Michael Ellerman , Andrew Morton , linuxppc-dev@lists.ozlabs.org, "David S. Miller" MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Implement arm64 support for patchable function pointers by emitting them as branch instructions (and a couple of NOPs in case the new target is out of range of a normal branch instruction.) Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 1 + arch/arm64/include/asm/ffp.h | 35 ++++++++++++++++++++ arch/arm64/kernel/insn.c | 22 ++++++++++++ 3 files changed, 58 insertions(+) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1b1a0e95c751..db8c9e51c56d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -102,6 +102,7 @@ config ARM64 select HAVE_ALIGNED_STRUCT_PAGE if SLUB select HAVE_ARCH_AUDITSYSCALL select HAVE_ARCH_BITREVERSE + select HAVE_ARCH_FFP select HAVE_ARCH_HUGE_VMAP select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_KASAN if !(ARM64_16K_PAGES && ARM64_VA_BITS_48) diff --git a/arch/arm64/include/asm/ffp.h b/arch/arm64/include/asm/ffp.h new file mode 100644 index 000000000000..678dc1262218 --- /dev/null +++ b/arch/arm64/include/asm/ffp.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef __ASM_FFP_H +#define __ASM_FFP_H + +struct ffp { + u32 insn[5]; + u32 def_branch; +}; + +#define DECLARE_FFP(_fn, _def) \ + extern typeof(_def) _fn; \ + extern struct ffp const __ffp_ ## _fn + +#define DEFINE_FFP(_fn, _def) \ + DECLARE_FFP(_fn, _def); \ + asm(" .pushsection \".text\", \"ax\", %progbits \n" \ + " .align 3 \n" \ + " .globl " #_fn " \n" \ + " .globl __ffp_" #_fn " \n" \ + #_fn " : \n" \ + "__ffp_" #_fn " : \n" \ + " b " #_def " \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " nop \n" \ + " b " #_def " \n" \ + " .popsection \n"); \ + EXPORT_SYMBOL(__ffp_ ## _fn) + +extern void ffp_set_target(const struct ffp *m, void *new_fn); +extern void ffp_reset_target(const struct ffp *m); + +#endif diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c index 2b3413549734..a2ed547fd171 100644 --- a/arch/arm64/kernel/insn.c +++ b/arch/arm64/kernel/insn.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1603,3 +1604,24 @@ u32 aarch64_insn_gen_extr(enum aarch64_insn_variant variant, insn = aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RN, insn, Rn); return aarch64_insn_encode_register(AARCH64_INSN_REGTYPE_RM, insn, Rm); } + +void ffp_set_target(const struct ffp *m, void *new_fn) +{ + u32 branch = aarch64_insn_gen_branch_imm((u64)m, (u64)new_fn, + AARCH64_INSN_BRANCH_NOLINK); + + if (branch == AARCH64_BREAK_FAULT) { + /* TODO out of range - use a PLT sequence instead */ + } else { + aarch64_insn_patch_text((void *[]){ (void *)m }, &branch, 1); + } +} +EXPORT_SYMBOL(ffp_set_target); + +void ffp_reset_target(const struct ffp *m) +{ + u32 branch = le32_to_cpu(m->def_branch); + + aarch64_insn_patch_text((void *[]){ (void *)m }, &branch, 1); +} +EXPORT_SYMBOL(ffp_reset_target);