From patchwork Tue Jan 26 17:10:38 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 60497 Delivered-To: patch@linaro.org Received: by 10.112.130.2 with SMTP id oa2csp2091632lbb; Tue, 26 Jan 2016 09:15:37 -0800 (PST) X-Received: by 10.98.40.194 with SMTP id o185mr35839709pfo.76.1453828537128; Tue, 26 Jan 2016 09:15:37 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id yu1si3143939pac.9.2016.01.26.09.15.36; Tue, 26 Jan 2016 09:15:37 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dkim=pass header.i=@linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S967167AbcAZRPf (ORCPT + 30 others); Tue, 26 Jan 2016 12:15:35 -0500 Received: from mail-wm0-f52.google.com ([74.125.82.52]:35247 "EHLO mail-wm0-f52.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S966843AbcAZRL2 (ORCPT ); Tue, 26 Jan 2016 12:11:28 -0500 Received: by mail-wm0-f52.google.com with SMTP id r129so113325985wmr.0 for ; Tue, 26 Jan 2016 09:11:27 -0800 (PST) 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=EZXeXfPt7mdOLD/wBUDY0bO8qCdISLRcj7dzAO+Klbs=; b=YffRHYgj5wFAepxbESZG9z3C7ja5qQEyiJeBFuBX7DVzZTf0lOxGGlWUZh6/jVc8RK zgcIw9cYeC1AYE/eTGyfPXD3Lzs3CQT6t0SW0gg2wU67rSYd6k8d83+veJo2FDoV5TSO UwxX9XOzs5u4PfrW47Gtgk7TDwqcUR414svvA= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=EZXeXfPt7mdOLD/wBUDY0bO8qCdISLRcj7dzAO+Klbs=; b=mJTTqYTEZakLvXHAaA+gkZDqJcI0CQfRIXY1QiJV4NUNlWG3E2d3ikjqbAqe0i9+ni ZrzYcIgI5TlpLiVXLmy6H2D4HRq8bauUdMMQSdBub4ObsoInQx87+6fJlLCPrDfKjety oG9vhthfqlgZLMRnE/DDPe8l0hdGvrk9pFuRHo4APijrZ5nguE62Ax1OVIIAbBhPXC9e QEIexjKy7V4LSeKABQWJm+ShtjOtN/gvp1s2YRskgRdxSHnY/4ixx7Vkhhm/utnfqk+X IUjCKzvL5tuVX881HgX/7nkyi1szYL428mi/GwcEKXIxKvyXBKjgktx0dmyI05iQh7bS 5wXg== X-Gm-Message-State: AG10YOQQ90zUUdli3wF3v0upFSZWN5DXCE/q+z3FxyO35ThRxHDBTO6LhrCXNc2J0wsTfPR7 X-Received: by 10.28.144.10 with SMTP id s10mr24323630wmd.97.1453828286899; Tue, 26 Jan 2016 09:11:26 -0800 (PST) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id ko2sm2328617wjc.9.2016.01.26.09.11.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 26 Jan 2016 09:11:25 -0800 (PST) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, kernel-hardening@lists.openwall.com, will.deacon@arm.com, catalin.marinas@arm.com, mark.rutland@arm.com, leif.lindholm@linaro.org, keescook@chromium.org, linux-kernel@vger.kernel.org Cc: stuart.yoder@freescale.com, bhupesh.sharma@freescale.com, arnd@arndb.de, marc.zyngier@arm.com, christoffer.dall@linaro.org, labbott@fedoraproject.org, matt@codeblueprint.co.uk, Ard Biesheuvel Subject: [PATCH v4 11/22] arm64: avoid R_AARCH64_ABS64 relocations for Image header fields Date: Tue, 26 Jan 2016 18:10:38 +0100 Message-Id: <1453828249-14467-12-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1453828249-14467-1-git-send-email-ard.biesheuvel@linaro.org> References: <1453828249-14467-1-git-send-email-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Unfortunately, the current way of using the linker to emit build time constants into the Image header will no longer work once we switch to the use of PIE executables. The reason is that such constants are emitted into the binary using R_AARCH64_ABS64 relocations, which are resolved at runtime, not at build time, and the places targeted by those relocations will contain zeroes before that. So refactor the endian swapping linker script constant generation code so that it emits the upper and lower 32-bit words separately. Signed-off-by: Ard Biesheuvel --- arch/arm64/include/asm/assembler.h | 11 +++++++ arch/arm64/kernel/head.S | 6 ++-- arch/arm64/kernel/image.h | 32 ++++++++++++-------- 3 files changed, 33 insertions(+), 16 deletions(-) -- 2.5.0 diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index d8bfcc1ce923..70f7b9e04598 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -222,4 +222,15 @@ lr .req x30 // link register .size __pi_##x, . - x; \ ENDPROC(x) + /* + * Emit a 64-bit absolute little endian symbol reference in a way that + * ensures that it will be resolved at build time, even when building a + * PIE binary. This requires cooperation from the linker script, which + * must emit the lo32/hi32 halves individually. + */ + .macro le64sym, sym + .long \sym\()_lo32 + .long \sym\()_hi32 + .endm + #endif /* __ASM_ASSEMBLER_H */ diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 85181cb60f46..2a39d4ab02bf 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -83,9 +83,9 @@ efi_head: b stext // branch to kernel start, magic .long 0 // reserved #endif - .quad _kernel_offset_le // Image load offset from start of RAM, little-endian - .quad _kernel_size_le // Effective size of kernel image, little-endian - .quad _kernel_flags_le // Informative flags, little-endian + le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian + le64sym _kernel_size_le // Effective size of kernel image, little-endian + le64sym _kernel_flags_le // Informative flags, little-endian .quad 0 // reserved .quad 0 // reserved .quad 0 // reserved diff --git a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h index bc2abb8b1599..b64c9b0a4492 100644 --- a/arch/arm64/kernel/image.h +++ b/arch/arm64/kernel/image.h @@ -26,21 +26,27 @@ * There aren't any ELF relocations we can use to endian-swap values known only * at link time (e.g. the subtraction of two symbol addresses), so we must get * the linker to endian-swap certain values before emitting them. + * + * Note that, in order for this to work when building the ELF64 PIE executable + * (for KASLR), these values should not be referenced via R_AARCH64_ABS64 + * relocations, since these are fixed up at runtime rather than at build time + * when PIE is in effect. So we need to split them up in 32-bit high and low + * words. */ #ifdef CONFIG_CPU_BIG_ENDIAN -#define DATA_LE64(data) \ - ((((data) & 0x00000000000000ff) << 56) | \ - (((data) & 0x000000000000ff00) << 40) | \ - (((data) & 0x0000000000ff0000) << 24) | \ - (((data) & 0x00000000ff000000) << 8) | \ - (((data) & 0x000000ff00000000) >> 8) | \ - (((data) & 0x0000ff0000000000) >> 24) | \ - (((data) & 0x00ff000000000000) >> 40) | \ - (((data) & 0xff00000000000000) >> 56)) +#define DATA_LE32(data) \ + ((((data) & 0x000000ff) << 24) | \ + (((data) & 0x0000ff00) << 8) | \ + (((data) & 0x00ff0000) >> 8) | \ + (((data) & 0xff000000) >> 24)) #else -#define DATA_LE64(data) ((data) & 0xffffffffffffffff) +#define DATA_LE32(data) ((data) & 0xffffffff) #endif +#define DEFINE_IMAGE_LE64(sym, data) \ + sym##_lo32 = DATA_LE32((data) & 0xffffffff); \ + sym##_hi32 = DATA_LE32((data) >> 32) + #ifdef CONFIG_CPU_BIG_ENDIAN #define __HEAD_FLAG_BE 1 #else @@ -58,9 +64,9 @@ * endian swapped in head.S, all are done here for consistency. */ #define HEAD_SYMBOLS \ - _kernel_size_le = DATA_LE64(_end - _text); \ - _kernel_offset_le = DATA_LE64(TEXT_OFFSET); \ - _kernel_flags_le = DATA_LE64(__HEAD_FLAGS); + DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \ + DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ + DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); #ifdef CONFIG_EFI