From patchwork Mon Jul 8 16:37:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 13726863 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id D2309C3DA41 for ; Mon, 8 Jul 2024 16:37:59 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 4EF5B6B00A2; Mon, 8 Jul 2024 12:37:59 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 49FDD6B00A3; Mon, 8 Jul 2024 12:37:59 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 27B886B00A5; Mon, 8 Jul 2024 12:37:59 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 09CCF6B00A2 for ; Mon, 8 Jul 2024 12:37:59 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 992801A13FD for ; Mon, 8 Jul 2024 16:37:58 +0000 (UTC) X-FDA: 82317142236.03.548CDFE Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf08.hostedemail.com (Postfix) with ESMTP id BB80A160020 for ; Mon, 8 Jul 2024 16:37:56 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=K3A9a5MP; spf=pass (imf08.hostedemail.com: domain of fweimer@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=fweimer@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1720456662; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=MpE9tc6GwVBdyYEbRi90TJl4jv833e7Ek5Pw4E3TGJE=; b=j9TYaZWFK858v3Ou6DY7vdiyUxp33gSh2i+c68yTs4929m9yF7pMAT7S2mbYJEjJi0N0T+ vtHl2H4MOLVde4R8jWz0vtxL9d/ONcwV6bshUfW2ref8Rj7nHN3GWBTGwymHdY5LvhOAyK Vhr7N+ch0umFibsx25KgwWZyIwA7KdY= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=K3A9a5MP; spf=pass (imf08.hostedemail.com: domain of fweimer@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=fweimer@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1720456662; a=rsa-sha256; cv=none; b=jNPzG7J7qgsIU2b+uh1yakmfkDHSMMIKeh6zZb/olte85TBc2XgQUJPcFgfkDcujYlm7u+ bHkU6aLS6bzWaNrFTIruAOhSqF4Ld198bspOWfJXDRFPVK6C7gLKInEn6emiGtg6+H/wQK PWiMA3mIt7nN3KGxd2+EpnG2sJ9JTDY= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720456676; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=MpE9tc6GwVBdyYEbRi90TJl4jv833e7Ek5Pw4E3TGJE=; b=K3A9a5MPQB6Wqzt+RHziDUEQKbeMhJMiThdk8xukMbyrE6oVc1gvBR5A1ajjM8ZW+l+U5g sHna25GKNk8X6DN0QPwJuErMChkjAg/DhUpuwfZ76oV+7reQzSGGrJljI9BQTpp3FG/PL9 +aoN96YmdsicyXsxH5/0yYApduBL8y4= Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-597-S3QDT4-CPfOc0o7haGvhuw-1; Mon, 08 Jul 2024 12:37:52 -0400 X-MC-Unique: S3QDT4-CPfOc0o7haGvhuw-1 Received: from mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.15]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 260D71955F41; Mon, 8 Jul 2024 16:37:38 +0000 (UTC) Received: from oldenburg.str.redhat.com (unknown [10.45.224.113]) by mx-prod-int-02.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id EC4371955F3B; Mon, 8 Jul 2024 16:37:17 +0000 (UTC) From: Florian Weimer To: =?utf-8?q?Micka=C3=ABl_Sala=C3=BCn?= Cc: Al Viro , Christian Brauner , Kees Cook , Linus Torvalds , Paul Moore , Theodore Ts'o , Alejandro Colomar , Aleksa Sarai , Andrew Morton , Andy Lutomirski , Arnd Bergmann , Casey Schaufler , Christian Heimes , Dmitry Vyukov , Eric Biggers , Eric Chiang , Fan Wu , Geert Uytterhoeven , James Morris , Jan Kara , Jann Horn , Jeff Xu , Jonathan Corbet , Jordan R Abrahams , Lakshmi Ramasubramanian , Luca Boccassi , Luis Chamberlain , "Madhavan T . Venkataraman" , Matt Bobrowski , Matthew Garrett , Matthew Wilcox , Miklos Szeredi , Mimi Zohar , Nicolas Bouchinet , Scott Shell , Shuah Khan , Stephen Rothwell , Steve Dower , Steve Grubb , Thibaut Sautereau , Vincent Strubel , Xiaoming Ni , Yin Fengwei , kernel-hardening@lists.openwall.com, linux-api@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org, linux-security-module@vger.kernel.org, Eric Biederman , linux-mm@kvack.org Subject: [PATCH] binfmt_elf: Fail execution of shared objects with ELIBEXEC (was: Re: [RFC PATCH v19 1/5] exec: Add a new AT_CHECK flag to execveat(2)) In-Reply-To: <20240708.zooj9Miaties@digikod.net> (=?utf-8?b?Ik1pY2thw6tsIFNh?= =?utf-8?b?bGHDvG4iJ3M=?= message of "Mon, 8 Jul 2024 10:56:59 +0200") References: <20240704190137.696169-1-mic@digikod.net> <20240704190137.696169-2-mic@digikod.net> <87bk3bvhr1.fsf@oldenburg.str.redhat.com> <20240706.poo9ahd3La9b@digikod.net> <871q46bkoz.fsf@oldenburg.str.redhat.com> <20240708.zooj9Miaties@digikod.net> Date: Mon, 08 Jul 2024 18:37:14 +0200 Message-ID: <878qybet6t.fsf_-_@oldenburg.str.redhat.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.15 X-Rspamd-Server: rspam03 X-Rspam-User: X-Rspamd-Queue-Id: BB80A160020 X-Stat-Signature: sij9cwpt7rg7rfnbauhdfaf7gk1ykxae X-HE-Tag: 1720456676-846075 X-HE-Meta: U2FsdGVkX1/I7BmIh8MIR+qo9p3mhMdKtqnzf37rhG/IXtoXY5eh0NV3qXaWoCk/Q9Olt7zJyVLmnGAg0qsVLuIrPCmQ77RBpJt80/8wqHwImYnU1CnAW6LH02i95RC7go5a5bDQiOVh/fQfK4XRTI9LwtxiYuO5gvkgNMPBT0zfdbFVdSrbdsVl7HbkXNw4TJxmTYKlsztUWH44rOVTfLWMlpQ5e/r6TP8CYzLLOR80QTeRyUfIaeyHt00DmS48uvu1QJSWNCSTRVzALUvEgg0OC70uOlH3d1aH2qf07U+sVH9Ok+MqDBAJiAOZbw0K9AJHy7yq5ETQAR891xevF1OofDxkwgzsxnVxlVNDT0VdQNHbdOYMPlwam4GOCIqTpJGXCMuMGsDxxwNMBHOuIh/axYgpfn+r3B95BFXXfU8d1cGkhyd6v8Cy5FgL8jQQJMbEzuIEZN22unMZyo+XLfAzpj2gbijFzsTONbAuIZSgj1Dhr6LRLbuNBGxLcg8Mc5aVIUL52uqIA9T1rvDlVRlwRcmXi+oOyFWLOoBRE+RpgZDeCzyVie+bR6iRgsm6GGQyuTioIlBcKFtnxHA15denYtx0Tae9d3wXoMWDZw5hCKSJIk9oPwqA0XNyyBZs8815a7xOW7HdSJzVulAQrc6TD+Z+QtNZQ2Yv9mKGEdxU60GlDA5ZN6jGUQMBa1DuU1WlS1fh5XA73f2AhE41vFkVEVGrCpGqMKWiIhTPUVmhDWp1sBTioxszt5smtsm6kXWcfs+NEIIynigTzttoCHpqX1zxoDRHjqmG2+yypUcbUJqufhML5ghklpfPlJHUg7mvb1nI4Ffgylp98wFqiA0n74bGC2z3WqkDIg8ItcvfnViLMjnqDFLO139xu9hCOqepxFf5fkLKYpGAylFS4H2dOoXKIL8ohpGt1w6GsqL3vpLSasuNt8v7OkGf9CZiS82IezawvsgYqRW2hGN 5Lbmj6IJ +bRMace41yjBVREIsQ37Thau4AEu5z+mAO7/HNtExeovqrfhPg0rVI3JIQHdQsVYWrBckcf5K/Oz2v4nvI96/i+BsfLHc0r/yBm/vq6JvYyI1JqT34xToWzAGcncwHg83LdiAnYOFC/T+VElFVbhlytF6UY78OrZ/CTYpnVKGY1MrJIjpWlcImBgAfCMW9QFsja59Xgv67RpoTs6d3qP9kiL0gRe3YwZGhcDEObKw0VAcuHdle+HnC+ncCMafL9posh3lcIz+50dxBsmsljX1ZN9tCFq5TuFyWdSz8bLDlJz8ijgbN29WwTiujytDfGDyPKFFW+b8HBEPIYxQ0591tsXqV64FDq5QE8Cp33+ATgfzUerpret5sRbwufPrvmhbAWA7 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: * Mickaël Salaün: > On Sat, Jul 06, 2024 at 05:32:12PM +0200, Florian Weimer wrote: >> * Mickaël Salaün: >> >> > On Fri, Jul 05, 2024 at 08:03:14PM +0200, Florian Weimer wrote: >> >> * Mickaël Salaün: >> >> >> >> > Add a new AT_CHECK flag to execveat(2) to check if a file would be >> >> > allowed for execution. The main use case is for script interpreters and >> >> > dynamic linkers to check execution permission according to the kernel's >> >> > security policy. Another use case is to add context to access logs e.g., >> >> > which script (instead of interpreter) accessed a file. As any >> >> > executable code, scripts could also use this check [1]. >> >> >> >> Some distributions no longer set executable bits on most shared objects, >> >> which I assume would interfere with AT_CHECK probing for shared objects. >> > >> > A file without the execute permission is not considered as executable by >> > the kernel. The AT_CHECK flag doesn't change this semantic. Please >> > note that this is just a check, not a restriction. See the next patch >> > for the optional policy enforcement. >> > >> > Anyway, we need to define the policy, and for Linux this is done with >> > the file permission bits. So for systems willing to have a consistent >> > execution policy, we need to rely on the same bits. >> >> Yes, that makes complete sense. I just wanted to point out the odd >> interaction with the old binutils bug and the (sadly still current) >> kernel bug. >> >> >> Removing the executable bit is attractive because of a combination of >> >> two bugs: a binutils wart which until recently always set the entry >> >> point address in the ELF header to zero, and the kernel not checking for >> >> a zero entry point (maybe in combination with an absent program >> >> interpreter) and failing the execve with ELIBEXEC, instead of doing the >> >> execve and then faulting at virtual address zero. Removing the >> >> executable bit is currently the only way to avoid these confusing >> >> crashes, so I understand the temptation. >> > >> > Interesting. Can you please point to the bug report and the fix? I >> > don't see any ELIBEXEC in the kernel. >> >> The kernel hasn't been fixed yet. I do think this should be fixed, so >> that distributions can bring back the executable bit. > > Can you please point to the mailing list discussion or the bug report? I'm not sure if this was ever reported upstream as an RFE to fail with ELIBEXEC. We have downstream bug report: Prevent executed .so files with e_entry == 0 from attempting to become a process. I've put together a patch which seems to work, see below. I don't think there's any impact on AT_CHECK with execveat because that mode will never get to this point. Thanks, Florian ---8<----------------------------------------------------------------- Subject: binfmt_elf: Fail execution of shared objects with ELIBEXEC Historically, binutils has used the start of the text segment as the entry point if _start was not defined. Executing such files results in crashes with random effects, depending on what code resides there. However, starting with binutils 2.38, BFD ld uses a zero entry point, due to commit 5226a6a892f922ea672e5775c61776830aaf27b7 ("Change the linker's heuristic for computing the entry point for binaries so that shared libraries default to an entry point of 0."). This means that shared objects with zero entry points are becoming more common, and it makes sense for the kernel to recognize them and refuse to execute them. For backwards compatibility, if a load segment does not map the ELF header at file offset zero, the kernel still proceeds as before, in case the file is very non-standard and can actually start executing at virtual offset zero. Signed-off-by: Florian Weimer diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index a43897b03ce9..ebd7052eb616 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -830,6 +830,7 @@ static int load_elf_binary(struct linux_binprm *bprm) unsigned long e_entry; unsigned long interp_load_addr = 0; unsigned long start_code, end_code, start_data, end_data; + bool elf_header_mapped = false; unsigned long reloc_func_desc __maybe_unused = 0; int executable_stack = EXSTACK_DEFAULT; struct elfhdr *elf_ex = (struct elfhdr *)bprm->buf; @@ -865,6 +866,9 @@ static int load_elf_binary(struct linux_binprm *bprm) continue; } + if (elf_ppnt->p_type == PT_LOAD && !elf_ppnt->p_offset) + elf_header_mapped = true; + if (elf_ppnt->p_type != PT_INTERP) continue; @@ -921,6 +925,20 @@ static int load_elf_binary(struct linux_binprm *bprm) goto out_free_ph; } + /* + * A zero value for e_entry means that the ELF file has no + * entry point. If the ELF header is mapped, this is + * guaranteed to crash (often even on the first instruction), + * so fail the execve system call instead. (This is most + * likely to happen for a shared object.) If the object has a + * program interpreter, dealing with the situation is its + * responsibility. + */ + if (elf_header_mapped && !elf_ex->e_entry && !interpreter) { + retval = -ELIBEXEC; + goto out_free_dentry; + } + elf_ppnt = elf_phdata; for (i = 0; i < elf_ex->e_phnum; i++, elf_ppnt++) switch (elf_ppnt->p_type) {