From patchwork Thu Apr 28 13:03:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Jon Medhurst \(Tixy\)" X-Patchwork-Id: 66898 Delivered-To: patch@linaro.org Received: by 10.140.93.198 with SMTP id d64csp203669qge; Thu, 28 Apr 2016 06:06:06 -0700 (PDT) X-Received: by 10.67.23.161 with SMTP id ib1mr19605938pad.156.1461848766153; Thu, 28 Apr 2016 06:06:06 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id th8si11651895pab.238.2016.04.28.06.06.06 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 28 Apr 2016 06:06:06 -0700 (PDT) Received-SPF: pass (google.com: best guess record for 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: best guess record for 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; dmarc=fail (p=NONE dis=NONE) header.from=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 1avlcL-0005bk-4v; Thu, 28 Apr 2016 13:04:29 +0000 Received: from smarthost03b.mail.zen.net.uk ([212.23.1.21]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1avlcE-0005Wt-Ab for linux-arm-kernel@lists.infradead.org; Thu, 28 Apr 2016 13:04:26 +0000 Received: from [82.69.122.217] (helo=linaro2) by smarthost03b.mail.zen.net.uk with esmtpsa (TLS1.2:RSA_AES_128_CBC_SHA1:128) (Exim 4.80) (envelope-from ) id 1avlbr-0005QK-Cx; Thu, 28 Apr 2016 13:03:59 +0000 Message-ID: <1461848638.2848.19.camel@linaro.org> Subject: [RFC PATCH] arm64: Make arch_randomize_brk avoid stack area From: "Jon Medhurst (Tixy)" To: Catalin Marinas , Will Deacon Date: Thu, 28 Apr 2016 14:03:58 +0100 X-Mailer: Evolution 3.12.9-1+b1 Mime-Version: 1.0 X-Originating-smarthost03b-IP: [82.69.122.217] X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160428_060422_537493_EA99D37A X-CRM114-Status: GOOD ( 22.16 ) X-Spam-Score: -1.9 (-) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.infradead.org summary: Content analysis details: (-1.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [212.23.1.21 listed in list.dnswl.org] 0.7 SPF_SOFTFAIL SPF: sender does not match SPF record (softfail) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 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: Kees Cook , linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org When a process is created, various address randomisations may end up colluding to place the address of brk in the stack memory. One consequence of this, is that even for processes that make no use of brk, the output of /proc/*/maps may show the stack area listed as '[heap]' rather than '[stack]'. Apart from being misleading to this causes fatal errors with the Android run-time like: "No [stack] line found in /proc/self/task/*/maps" To prevent this problem pick a limit for brk that allows for the stack's memory. At the same time we remove randomize_base() as that was only used by arch_randomize_brk(). Note, in practice, since commit d1fd836dcf00 ("mm: split ET_DYN ASLR from mmap ASLR") this problem shouldn't occur because the address chosen for loading binaries is well clear of the stack, however, prior to that the problem does occur because of the following... The memory layout of a task is determined by arch_pick_mmap_layout. If address randomisation is enabled (task has flag PF_RANDOMIZE) this sets mmap_base to a random address at the top of task memory just below a region calculated to allow for a stack which itself may have a random base address. Any mmap operations that then happen which require an address allocating will use the topdown allocation method, i.e. the first allocated memory will be at the top of memory, just below the area set aside for the stack. When a relocatable binary is loaded into a new process by load_elf_binary and randomised address are enabled, it uses a 'load_bias' of zero, so that when mmap is called to create a memory region for it, a new address is picked (address zero not being available). As this is the first memory region in the task, it gets the region just below the stack, as described previously. The loader then set's brk to the end of the elf data section, which will be near the end of the loaded binary and then it calls arch_randomize_brk. As this currently stands, this adds a random amount to brk, which unfortunately may take it into the address range where the stack lies. Signed-off-by: Jon Medhurst --- I don't know if a change like this is needed for the latest Linux versions - where it's more like defensive coding than solving a current issue. For earlier versions, like 3.18 LTS where I diagnosed the problem, I don't know if this is a suitable fix, of if the later ASLR changes should be backported (seems somewhat more invasive). Perhaps this issue isn't important enough for LTS and is just needed for people maintaining Android trees. arch/arm64/kernel/process.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) -- 2.1.4 _______________________________________________ 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/kernel/process.c b/arch/arm64/kernel/process.c index 8062482..7126a5a 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -382,13 +382,24 @@ unsigned long arch_align_stack(unsigned long sp) return sp & ~0xf; } -static unsigned long randomize_base(unsigned long base) +unsigned long arch_randomize_brk(struct mm_struct *mm) { unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1; - return randomize_range(base, range_end, 0) ? : base; -} + unsigned long max_stack, range_limit; -unsigned long arch_randomize_brk(struct mm_struct *mm) -{ - return randomize_base(mm->brk); + /* + * Determine how much room do we need to leave available for the stack. + * We limit this to a reasonable value, because extremely large or + * unlimited stacks are always going to bump up against brk at some + * point and we don't want to fail to randomise brk in those cases. + */ + max_stack = rlimit(RLIMIT_STACK); + if (max_stack > SZ_128M) + max_stack = SZ_128M; + + range_limit = mm->start_stack - max_stack - 1; + if (range_end > range_limit) + range_end > range_limit + + return randomize_range(mm->brk, range_end, 0) ? : mm->brk; }