Received: by 2002:a25:b323:0:0:0:0:0 with SMTP id l35csp357436ybj; Thu, 19 Sep 2019 15:40:29 -0700 (PDT) X-Google-Smtp-Source: APXvYqwJByHETF9UZpEIBwhppMSDbrxO08XLobcpRA9t8DgaPgzx7vfKbL8PVsH9hVKz6ZFMlGmq X-Received: by 2002:a50:ac03:: with SMTP id v3mr18798186edc.113.1568932829772; Thu, 19 Sep 2019 15:40:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1568932829; cv=none; d=google.com; s=arc-20160816; b=N6b7YyBmUxhW5jdbnevzPgDlVgN6sHG/inr7IymzfVmVmRQTFJBK9hlpW5eBw1f0e/ YPfQC04ACkWYB2yx1DZ6Yd8aVPuYnLNePlMzfasRq01QZ0d0ZtCjFTwfw/Ki2/Jsi2nM FUTeWtUfh+XViMeOT2pYkeEwe/evu4pjW1vaQ4CfkcyM2V6anCZocTiC4fmDtvauoz2L fWHst1x8L5EImOeE3KZ6xftARm5JbzvmjNff3S401FRkl28SrwCSCYRi/yxuBI1qLJvf s4YE8VJGDsZKnlDMlVNUEnDbgSmr7vQcefE/TSe/kfimvB1Ti8XZSfc+bySKQ6KE0a+g ue9w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=R5q6/4jOeqhyFp97McPnXnbnRS+IIiF8MawnPatyqQ4=; b=mbzY5ZpQTW3Kx8kdluGkoDpwdNWiWzbPp+S1ri0cRJrF4/pf0aDK4A2n/yi7bKczpJ BlcZS9RMezb1wrkYTnYB07FQ5ckZymnzr3Zq8RoK+u0DdUf85mZkAvWbcDU9+OuzcY6n LV3b7Y5gdhE9HVlWlzFmNwdsnM+5uS18bONhUKRy6J7ALvv21cORbc4ib7v5StxY7jev yL7fYb/n9LJhVrigdvs346b4QSBSW77e6AyP8+rqjfWOAWNRsgQncMlm4H2xAV8Z5e8j c1NnpvyFOHHNihJNijB9MUTc0xuygy2vHLSIAXsdwHoMF5txJ+/TdKtWkTZbt/JAXk2V 0yzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=lx3s+VaK; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id e57si95692ede.356.2019.09.19.15.40.06; Thu, 19 Sep 2019 15:40:29 -0700 (PDT) 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; dkim=pass header.i=@kernel.org header.s=default header.b=lx3s+VaK; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2406122AbfISWP0 (ORCPT + 99 others); Thu, 19 Sep 2019 18:15:26 -0400 Received: from mail.kernel.org ([198.145.29.99]:55334 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2391160AbfISWPY (ORCPT ); Thu, 19 Sep 2019 18:15:24 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 01CEF21920; Thu, 19 Sep 2019 22:15:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1568931323; bh=QPUXf+cTwzJXSswBNdt4UQo6NtcMvzIJOFMWaa4BDs4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=lx3s+VaKT8Kl0LfoUbEBa3WpGULoMKbj/Gj9/io20nUtj87yWolmk4K7u0pWocCBV dG5Nbmoy1wZ+P0Xe5xMdlYWqfDTu0pDNeKsCvvd3Ep62ur4GWgP1lCVNeuJob7Is2+ LpVJ5vW8lslGbKtbOUb3d+OnnyBhf41yF0dGn6FI= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kees Cook , Ali Saidi , Guenter Roeck , Michal Hocko , Matthew Wilcox , Thomas Gleixner , Jann Horn , Andrew Morton , Linus Torvalds , Frank van der Linden Subject: [PATCH 4.19 77/79] binfmt_elf: move brk out of mmap when doing direct loader exec Date: Fri, 20 Sep 2019 00:04:02 +0200 Message-Id: <20190919214814.582627738@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190919214807.612593061@linuxfoundation.org> References: <20190919214807.612593061@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Kees Cook commit bbdc6076d2e5d07db44e74c11b01a3e27ab90b32 upstream. Commmit eab09532d400 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE"), made changes in the rare case when the ELF loader was directly invoked (e.g to set a non-inheritable LD_LIBRARY_PATH, testing new versions of the loader), by moving into the mmap region to avoid both ET_EXEC and PIE binaries. This had the effect of also moving the brk region into mmap, which could lead to the stack and brk being arbitrarily close to each other. An unlucky process wouldn't get its requested stack size and stack allocations could end up scribbling on the heap. This is illustrated here. In the case of using the loader directly, brk (so helpfully identified as "[heap]") is allocated with the _loader_ not the binary. For example, with ASLR entirely disabled, you can see this more clearly: $ /bin/cat /proc/self/maps 555555554000-55555555c000 r-xp 00000000 ... /bin/cat 55555575b000-55555575c000 r--p 00007000 ... /bin/cat 55555575c000-55555575d000 rw-p 00008000 ... /bin/cat 55555575d000-55555577e000 rw-p 00000000 ... [heap] ... 7ffff7ff7000-7ffff7ffa000 r--p 00000000 ... [vvar] 7ffff7ffa000-7ffff7ffc000 r-xp 00000000 ... [vdso] 7ffff7ffc000-7ffff7ffd000 r--p 00027000 ... /lib/x86_64-linux-gnu/ld-2.27.so 7ffff7ffd000-7ffff7ffe000 rw-p 00028000 ... /lib/x86_64-linux-gnu/ld-2.27.so 7ffff7ffe000-7ffff7fff000 rw-p 00000000 ... 7ffffffde000-7ffffffff000 rw-p 00000000 ... [stack] $ /lib/x86_64-linux-gnu/ld-2.27.so /bin/cat /proc/self/maps ... 7ffff7bcc000-7ffff7bd4000 r-xp 00000000 ... /bin/cat 7ffff7bd4000-7ffff7dd3000 ---p 00008000 ... /bin/cat 7ffff7dd3000-7ffff7dd4000 r--p 00007000 ... /bin/cat 7ffff7dd4000-7ffff7dd5000 rw-p 00008000 ... /bin/cat 7ffff7dd5000-7ffff7dfc000 r-xp 00000000 ... /lib/x86_64-linux-gnu/ld-2.27.so 7ffff7fb2000-7ffff7fd6000 rw-p 00000000 ... 7ffff7ff7000-7ffff7ffa000 r--p 00000000 ... [vvar] 7ffff7ffa000-7ffff7ffc000 r-xp 00000000 ... [vdso] 7ffff7ffc000-7ffff7ffd000 r--p 00027000 ... /lib/x86_64-linux-gnu/ld-2.27.so 7ffff7ffd000-7ffff7ffe000 rw-p 00028000 ... /lib/x86_64-linux-gnu/ld-2.27.so 7ffff7ffe000-7ffff8020000 rw-p 00000000 ... [heap] 7ffffffde000-7ffffffff000 rw-p 00000000 ... [stack] The solution is to move brk out of mmap and into ELF_ET_DYN_BASE since nothing is there in the direct loader case (and ET_EXEC is still far away at 0x400000). Anything that ran before should still work (i.e. the ultimately-launched binary already had the brk very far from its text, so this should be no different from a COMPAT_BRK standpoint). The only risk I see here is that if someone started to suddenly depend on the entire memory space lower than the mmap region being available when launching binaries via a direct loader execs which seems highly unlikely, I'd hope: this would mean a binary would _not_ work when exec()ed normally. (Note that this is only done under CONFIG_ARCH_HAS_ELF_RANDOMIZATION when randomization is turned on.) Link: http://lkml.kernel.org/r/20190422225727.GA21011@beast Link: https://lkml.kernel.org/r/CAGXu5jJ5sj3emOT2QPxQkNQk0qbU6zEfu9=Omfhx_p0nCKPSjA@mail.gmail.com Fixes: eab09532d400 ("binfmt_elf: use ELF_ET_DYN_BASE only for PIE") Signed-off-by: Kees Cook Reported-by: Ali Saidi Cc: Ali Saidi Cc: Guenter Roeck Cc: Michal Hocko Cc: Matthew Wilcox Cc: Thomas Gleixner Cc: Jann Horn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds Cc: Frank van der Linden Signed-off-by: Greg Kroah-Hartman --- fs/binfmt_elf.c | 11 +++++++++++ 1 file changed, 11 insertions(+) --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -1137,6 +1137,17 @@ static int load_elf_binary(struct linux_ current->mm->start_stack = bprm->p; if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) { + /* + * For architectures with ELF randomization, when executing + * a loader directly (i.e. no interpreter listed in ELF + * headers), move the brk area out of the mmap region + * (since it grows up, and may collide early with the stack + * growing down), and into the unused ELF_ET_DYN_BASE region. + */ + if (IS_ENABLED(CONFIG_ARCH_HAS_ELF_RANDOMIZE) && !interpreter) + current->mm->brk = current->mm->start_brk = + ELF_ET_DYN_BASE; + current->mm->brk = current->mm->start_brk = arch_randomize_brk(current->mm); #ifdef compat_brk_randomized