From mboxrd@z Thu Jan 1 00:00:00 1970 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 474EFC5B543 for ; Tue, 10 Jun 2025 04:04:41 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D210C6B007B; Tue, 10 Jun 2025 00:04:40 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id CD1B86B0089; Tue, 10 Jun 2025 00:04:40 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BE8A96B008A; Tue, 10 Jun 2025 00:04:40 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 9C22C6B007B for ; Tue, 10 Jun 2025 00:04:40 -0400 (EDT) Received: from smtpin30.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay06.hostedemail.com (Postfix) with ESMTP id 4C9EA1016FF for ; Tue, 10 Jun 2025 04:04:40 +0000 (UTC) X-FDA: 83538149520.30.04C1C51 Received: from sea.source.kernel.org (sea.source.kernel.org [172.234.252.31]) by imf08.hostedemail.com (Postfix) with ESMTP id 7DD78160012 for ; Tue, 10 Jun 2025 04:04:38 +0000 (UTC) Authentication-Results: imf08.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Wq0ePe08; spf=pass (imf08.hostedemail.com: domain of kees@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=kees@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1749528278; 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: in-reply-to:in-reply-to:references:references:dkim-signature; bh=CHmIP34MikFZNFLoCiBMT7cILbEvtI+vQqEcJ1rTRgA=; b=X95ctItKbxhHZkJosY7E2LX4G/KhSVYSLStzBxEwyMP1k+qXcYAcIDBX+jwwu/cbB3EXm4 cwmV55bjzEuZgHjhiZYhoeKp32WmctrVYf9qDdsyClVKLhyyN07Ghvqdqkn9WMHIxtvvC9 Gu2LABTqPY4uDD08jux8F/f5YeKAM4g= ARC-Authentication-Results: i=1; imf08.hostedemail.com; dkim=pass header.d=kernel.org header.s=k20201202 header.b=Wq0ePe08; spf=pass (imf08.hostedemail.com: domain of kees@kernel.org designates 172.234.252.31 as permitted sender) smtp.mailfrom=kees@kernel.org; dmarc=pass (policy=quarantine) header.from=kernel.org ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1749528278; a=rsa-sha256; cv=none; b=oMddKWrmYMeBKs95k5mAsTcWYneBaZDHE9AXab8JQL/ou+oVdFqW+oEFtLjYOfCAx068id FY/nB/USNIm4hYVQugg7tV3BKqjoImmXyODD1xKD3DLp7iC0TE6XocOdfkTdE9kmE2KpsL mZ90BULDXkr8RWCefbkpxiPudWbyu50= Received: from smtp.kernel.org (transwarp.subspace.kernel.org [100.75.92.58]) by sea.source.kernel.org (Postfix) with ESMTP id 2A1B843666; Tue, 10 Jun 2025 04:04:37 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 002EEC4CEEF; Tue, 10 Jun 2025 04:04:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1749528277; bh=aVnJbC3z4nwrmfypL0Oi6Gf1QoMq9GB7sy1Q0NerLR8=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=Wq0ePe08BqT+ES0gpcmY92ykXFtKKa+HuUt26Kfn0ERlyV9OUGnJ2OQwKuqgxwF91 svtoihBgrR41xsCAkR6Dvec7dFKveCKHQN7PLYbhSFYXwu5DVXvnyjBU+8QlUJaOwP YIdeFa5fUJe6aYmS1+i3bHM4TwB14sbrJj4fhZ6oKvjIleGvkgQW5ExV2OcncGpAMw 5rqkgEvOYu2joguoZgODKd85X3+DZmMQ8r3GtVopJ4zK5H46iOSqambHDDZFkPHl8s IrPDeI4ygHtfTmEflaXVkKxDvnAJe6DnSDAH0KxNNnJwKoiSMy65z73dBQu5GtSO08 W2jLe8TPrOReg== Date: Mon, 9 Jun 2025 21:04:36 -0700 From: Kees Cook To: Pranav Tyagi Cc: viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, skhan@linuxfoundation.org, linux-kernel-mentees@lists.linux.dev Subject: Re: [PATCH] binfmt_elf: use check_mul_overflow() for size calc Message-ID: <202506092053.827AD89DC5@keescook> References: <20250607082844.8779-1-pranav.tyagi03@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20250607082844.8779-1-pranav.tyagi03@gmail.com> X-Rspamd-Queue-Id: 7DD78160012 X-Stat-Signature: 99on9gfhhges9twz4df467jaoz5uu13g X-Rspam-User: X-Rspamd-Server: rspam04 X-HE-Tag: 1749528278-329161 X-HE-Meta: U2FsdGVkX1/Qc2YLKZ1b4JnG84E8wWTW+wpmNeWUMN/X/i6Hx7Ut1Yflx0lzHKJqkhDTmH1LluklwlUxCV7tMSjhoO4SgQTAIKbwF8qQEJBROMC8Itb5MFUxBLL8zlrzGkqLMDj/MUghwwJbnVL1+F5ZPEOiUiSDOSsPo+eThf77DDhl1CQInmdw8dvhpAMrckVPk1TD25IraMBSRkA8eyQ9YJ8tdQ40RbsuZh80J79iRerS3QkRS7h0AiN3KY/z7bL3KQWsTCX6SMvDkfT82ivaDEkl+GIokGUNmgbwkVJLUsmMEnX87OUz2i5uqsvvzdv0rGhCSjWd2Ur47Hbodd/xdsh1MvDJZE7A3XoEAo6hqu21ZU4hl3MTj2EEQNlgRpZAuN4cMrqCQncnHQaEuyiSCqSvyX0inMzaWcPBuu2vrgN+sPEKFAKBGytEmMJKVdQsQ2T16XYV2dlnrj1rHhbRD4qQFbREEbGWQQe+I4p6VC3NMSu+JQ9MqZch4LdtCpyg/cSH4fRiRBSkuMhm3ukR7nfSj/UCbmmdfvHtPhJmvN7BDT7aURjLbFs2svU70t6i82be+R1Xf2vthrXWhcSS9piTSu5KEV5/FuKDFHvN1VczgtQW0ZRC+lDYRBgOXI7K5703USr2ADW/sgxzfrRm+7oMTOeUDXkpinUJPQYr8UemCPsVy3UdiuiFH5DoyZNsbt3FTo9OG611hhCO/DSjtqy4n4+1C9zXxuYFSYVkv3h0ozAhcWglJ/UG5Y3U3xRMWMEVqd6KMmwVuOe230UYy9J/zPc1HablGrbU60M44DUwlyegCkZJxF35/lKMXp6lSqOBJrdw9JUN63QTd8Hb9pZ18+Nz9v67VII7YbHQK1d26XoEHqMACAXkNcj+37VW1nChDV5RckPnHAjDZhZL7bx6LuOAtA/QtTQ9wW6WhQl7MLTyOV50j36kNc9x0gEhajRWjYXHz9hfOvx FKnWqWxl 79HpI/Qd+MhQaq5DcLJKyXv18ka/36HVOfa6mQKGb9YL+9nTPACUNSEhnRpIakDufX9zvDC8gGknsX5funlwS1xao3iUnJEtK9G7w19aIQJt1qbTwbFck7Zt8w2O5zJ2xHDZotD0njM+w+m5q0LzeF6Kw/jZ4pZ/rsjfm0CkSTRUWicysQGod9w6tY8CSXyId2ZQk8m/ohbBPTHmAR1dUtaCw5I4T7fSnvsN/p3Xs6EACaiV7YkjKqarfaj9oKOnDEH2fGg7ONBWrgg8rcJw+8vDIMaYjQCPsuGEoMUh7xtrxAKRluScdpaAjtl+AUbnL+aAStxDv76uriodJP0OdcV3ElB/ZkT+cU4QTOzShcWqsQRMPC5YzObB+YGpSml24I/idHfxC9X4REz/+bN0yA2FHwX9jrZ+OqId/JB4KzWU13l/3dm92ZzhIVgJmEDzQlA/fZsb1BopA8y84WGNI9G6DUuMBg9BJafsg 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: On Sat, Jun 07, 2025 at 01:58:44PM +0530, Pranav Tyagi wrote: > Use check_mul_overflow() to safely compute the total size of ELF program > headers instead of relying on direct multiplication. > > Directly multiplying sizeof(struct elf_phdr) with e_phnum risks integer > overflow, especially on 32-bit systems or with malformed ELF binaries > crafted to trigger wrap-around. If an overflow occurs, kmalloc() could > allocate insufficient memory, potentially leading to out-of-bound > accesses, memory corruption or security vulnerabilities. > > Using check_mul_overflow() ensures the multiplication is performed > safely and detects overflows before memory allocation. This change makes > the function more robust when handling untrusted or corrupted binaries. > > Signed-off-by: Pranav Tyagi > Link: https://github.com/KSPP/linux/issues/92 > --- > fs/binfmt_elf.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c > index a43363d593e5..774e705798b8 100644 > --- a/fs/binfmt_elf.c > +++ b/fs/binfmt_elf.c > @@ -518,7 +518,10 @@ static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex, > > /* Sanity check the number of program headers... */ > /* ...and their total size. */ > - size = sizeof(struct elf_phdr) * elf_ex->e_phnum; size is unsigned int, which has a maximum value of 4,294,967,295. elf_ex->e_phnum is a u16 (2 bytes) and will not be changing: $ pahole -C elf64_hdr */fs/binfmt_elf.o struct elf64_hdr { ... Elf64_Half e_phnum; /* 56 2 */ ... $ pahole -C Elf64_Half */fs/binfmt_elf.o typedef __u16 Elf64_Half; So it has a maximum value of 65,535. sizeof(struct elf_phdr) is a fixed value, 56: $ pahole -C elf64_phdr */fs/binfmt_elf.o struct elf64_phdr { ... /* size: 56, cachelines: 1, members: 8 */ /* last cacheline: 56 bytes */ }; So the maximum product of the two is 3,669,960. It is not possible for this calculation to overflow. > + > + if (check_mul_overflow(sizeof(struct elf_phdr), elf_ex->e_phnum, &size)) > + goto out; > + You can even see that the entire check would be elided by the compiler: #include unsigned int unchecked(Elf64_Ehdr *elf_ex) { unsigned int size; size = sizeof(Elf64_Phdr) * elf_ex->e_phnum; return size; } unsigned int checked(Elf64_Ehdr *elf_ex) { unsigned int size; if (__builtin_mul_overflow(sizeof(Elf64_Phdr), elf_ex->e_phnum, &size)) return 0; return size; } ...produces this assembler, identical for both functions: unchecked: movzx eax, WORD PTR [rdi+56] imul eax, eax, 56 ret checked: movzx eax, WORD PTR [rdi+56] imul eax, eax, 56 ret https://godbolt.org/z/hTEef8cT9 -Kees -- Kees Cook