From patchwork Mon Feb 8 10:12:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 61386 Delivered-To: patch@linaro.org Received: by 10.112.43.199 with SMTP id y7csp1345788lbl; Mon, 8 Feb 2016 02:14:44 -0800 (PST) X-Received: by 10.66.121.167 with SMTP id ll7mr4173388pab.6.1454926484638; Mon, 08 Feb 2016 02:14:44 -0800 (PST) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id va5si45633620pac.165.2016.02.08.02.14.44 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Feb 2016 02:14:44 -0800 (PST) Received-SPF: pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dkim=neutral (body hash did not verify) header.i=@linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1aSioM-0004te-Di; Mon, 08 Feb 2016 10:12:50 +0000 Received: from mail-wm0-x22b.google.com ([2a00:1450:400c:c09::22b]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1aSioH-0004k6-C2 for linux-arm-kernel@lists.infradead.org; Mon, 08 Feb 2016 10:12:48 +0000 Received: by mail-wm0-x22b.google.com with SMTP id 128so148017770wmz.1 for ; Mon, 08 Feb 2016 02:12:24 -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=880zSCMi8/AGlSvd3QAqN97SqIjNxqJQxtcvPRcaOWc=; b=kZPxsASDzvzsO3MXT3ol8Oocoa+pQy3lSP2g7jI69dPwsp6gRaZnu/s71Bo0VdXiGl w19dcVWfX7tXDzDdbaqU7PFU1e2lwynOwseSEMGzVSF7rxg+idUlktRDO5MtSjxltMil Hpt70WACy8k9wkoP7zHCi2ipwTBNxrdhmJmXg= 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=880zSCMi8/AGlSvd3QAqN97SqIjNxqJQxtcvPRcaOWc=; b=MqQWoI3rLhg5J0TqQ3cPhGdDrBL/YeutLo7O9pZmGsuv832DTjcqhRgI3KrQ7SZ6F7 fWKiZt4SX77qQzEAFyJwdKWr0OYA6DeIa/fOpwxrYS27a/HrA4+kSSKPv19m3WwuVqC1 Zoc67/xf6OZjc+S5LOwpdFhVRSGD3cjBQD7aIwPAMMV957DE4pdwAH3nGBF1o2qZ9l/5 QJtrfmb9SvD0j31Q7bhoHmVBtsIsxrzkP4jKYY30cNn6C3DR2Ib4x8hoMMdLfPS3mANz VUiR/Sr9C7uKL3U6VSFnZ3iZDXZWikY3Nbo/0J2pGzgv0yHeeigtcKhOlq4BDPIcH0z2 MAYg== X-Gm-Message-State: AG10YOQ6LkKHAGpS5GeB9/zijwkmrycZWzqNO0nbZrVWO4lyz5vpFVjackAGsONlhN3mjElw X-Received: by 10.28.179.84 with SMTP id c81mr50594269wmf.30.1454926343228; Mon, 08 Feb 2016 02:12:23 -0800 (PST) Received: from localhost.localdomain ([195.55.142.58]) by smtp.gmail.com with ESMTPSA id 73sm11916715wmm.7.2016.02.08.02.12.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 08 Feb 2016 02:12:22 -0800 (PST) From: Ard Biesheuvel To: linux-arm-kernel@lists.infradead.org, catalin.marinas@arm.com, will.deacon@arm.com, mark.rutland@arm.com, keescook@chromium.org Subject: [PATCH] arm64: allow the module region to be randomized independently Date: Mon, 8 Feb 2016 11:12:12 +0100 Message-Id: <1454926332-25929-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: References: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160208_021245_869717_BBF520B0 X-CRM114-Status: GOOD ( 20.05 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2a00:1450:400c:c09:0:0:0:22b listed in] [list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org This patch applies directly onto '[PATCH v5sub2 7/8] arm64: add support for kernel ASLR' so it can be folded in or applied separately, as desired. As pointed out by Kees, fully randomizing each module allocation does not add anything in terms of security, and only hurts performance even more, since it would cause all inter-module branches to be resolved via veneers as well. ----------8<-------------- This adds the option to randomize the module region independently from the core kernel, and enables it by default. This makes it less likely that the location of core kernel data structures can be determined by an adversary, but causes all function calls from modules into the core kernel to be resolved via entries in the module PLTs. Signed-off-by: Ard Biesheuvel --- arch/arm64/Kconfig | 15 ++++++++ arch/arm64/include/asm/module.h | 6 ++++ arch/arm64/kernel/kaslr.c | 36 +++++++++++++++----- arch/arm64/kernel/module.c | 9 ++--- 4 files changed, 50 insertions(+), 16 deletions(-) -- 2.5.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e3049d5c1246..666aacc4c763 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -787,6 +787,21 @@ config RANDOMIZE_BASE If unsure, say N. +config RANDOMIZE_MODULE_REGION_FULL + bool "Randomize the module region independently from the core kernel" + depends on RANDOMIZE_BASE + default y + help + Randomizes the location of the module region without considering the + location of the core kernel. This way, it is impossible for modules + to leak information about the location of core kernel data structures + but it does imply that function calls between modules and the core + kernel will need to be resolved via veneers in the module PLT. + + When this option is not set, the module region will be randomized over + a limited range that contains the [_stext, _etext] interval of the + core kernel, so branch relocations are always in range. + endmenu menu "Boot options" diff --git a/arch/arm64/include/asm/module.h b/arch/arm64/include/asm/module.h index 8652fb613304..e12af6754634 100644 --- a/arch/arm64/include/asm/module.h +++ b/arch/arm64/include/asm/module.h @@ -31,4 +31,10 @@ struct mod_arch_specific { u64 module_emit_plt_entry(struct module *mod, const Elf64_Rela *rela, Elf64_Sym *sym); +#ifdef CONFIG_RANDOMIZE_BASE +extern u64 module_alloc_base; +#else +#define module_alloc_base ((u64)_etext - MODULES_VSIZE) +#endif + #endif /* __ASM_MODULE_H */ diff --git a/arch/arm64/kernel/kaslr.c b/arch/arm64/kernel/kaslr.c index b0bf628ba51f..7a40aa4ba93d 100644 --- a/arch/arm64/kernel/kaslr.c +++ b/arch/arm64/kernel/kaslr.c @@ -20,7 +20,7 @@ #include #include -u32 __read_mostly module_load_offset; +u64 __read_mostly module_alloc_base; static __init u64 get_kaslr_seed(void *fdt) { @@ -126,14 +126,32 @@ u64 __init kaslr_early_init(u64 dt_phys) (((u64)_end + offset) >> SWAPPER_TABLE_SHIFT)) offset = (offset + (u64)(_end - _text)) & mask; - /* - * Randomize the module region, by setting module_load_offset to - * a PAGE_SIZE multiple in the interval [0, module_range). This - * ensures that the resulting region still covers [_stext, _etext], - * and that all relative branches can be resolved without veneers. - */ - module_range = MODULES_VSIZE - (u64)(_etext - _stext); - module_load_offset = ((module_range * (u16)seed) >> 16) & PAGE_MASK; + if (IS_ENABLED(CONFIG_RANDOMIZE_MODULE_REGION_FULL)) { + /* + * Randomize the module region independently from the core + * kernel. This prevents modules from leaking any information + * about the address of the kernel itself, but results in + * branches between modules and the core kernel that are + * resolved via PLTs. (Branches between modules will be + * resolved normally.) + */ + module_range = VMALLOC_END - VMALLOC_START - MODULES_VSIZE; + module_alloc_base = VMALLOC_START; + } else { + /* + * Randomize the module region by setting module_alloc_base to + * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE, + * _stext) . This guarantees that the resulting region still + * covers [_stext, _etext], and that all relative branches can + * be resolved without veneers. + */ + module_range = MODULES_VSIZE - (u64)(_etext - _stext); + module_alloc_base = (u64)_etext + offset - MODULES_VSIZE; + } + + /* use the lower 21 bits to randomize the base of the module region */ + module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21; + module_alloc_base &= PAGE_MASK; return offset; } diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index 54702d456680..dfa1ffaa9844 100644 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -33,14 +33,9 @@ void *module_alloc(unsigned long size) { void *p; - u64 base = (u64)_etext - MODULES_VSIZE; - if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { - extern u32 module_load_offset; - base += module_load_offset; - } - - p = __vmalloc_node_range(size, MODULE_ALIGN, base, base + MODULES_VSIZE, + p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, + module_alloc_base + MODULES_VSIZE, GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0));