Received: by 2002:a05:6a10:2726:0:0:0:0 with SMTP id ib38csp1014111pxb; Wed, 6 Apr 2022 06:44:55 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyN3Dznufo8Ho81JMdWRcqOj24ycLsDKGePEP+GJ8L6AUdyI0FEJjftFK2mJpcr1FKWI+PC X-Received: by 2002:a63:ec52:0:b0:39c:b5f3:7b25 with SMTP id r18-20020a63ec52000000b0039cb5f37b25mr1212368pgj.224.1649252695456; Wed, 06 Apr 2022 06:44:55 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649252695; cv=none; d=google.com; s=arc-20160816; b=lwLwYuT4i35V/9hCk9hHxWfuBP4MZiW8DN7ndwdG+0UpygFMeX13q/78pIzMLI5TUs jnLSuT4e461wMLxGb/4JuQUECY4YD2DJemLpWSe4UUBD8cPFXoTVC402u/UJ9fqDYQkt /wvTICWlfpk8/TLhnojVHxHHm8orhrNIiNw0LP0k0GitiAheRQKOR5CKGaDroZfc+eMR jP3hqkjNeg3xftqtg4My38l3uru3i1w0vCqf0sRYG7NrtNBRKr4pqzhW/bRWjINWlGlr IFDVgnjNop6tg4X16fdwO83EP34E8BoEJSBqZNW9qiNisTXhnhkTXjNAlTV1HcYr8GQV VyZQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=houj9DzC9MpATO/+L/jklBFuzQpHbvPMO3esZPca9+o=; b=E7gPpRTg33IGdhtoUG75ggN5CM0QEfU3B3oXB78WfkRMJVmtbk/4ktwhhnSq06laIe nKu/fWvlSoJ2LnRP49X6WofRBsU/ogDTaqFHSrM+GczXkhFnzSM05twIpothkXS6pHOu +8IPXk4eCypvLijn7z38SYbQDlzKFGki9iIiPIp9r/xohmmBNNRo1SOJwzROyQZeAbjc t3SHgrclP5RF+szVvgvbDlaBuVsEG0nga31BsXqPpH7pAYQhXY+IOUHXzFhFbBKougQD C+ArmgXncR3CR7YXcdXgAuH74WDPv5BxBwKxLE2CGde+9dMqO9NWJBvZy2g+O5MkKxP6 PM9A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=a0Peh79g; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [2620:137:e000::1:18]) by mx.google.com with ESMTPS id a2-20020a170902900200b00153b2d165d8si14937935plp.480.2022.04.06.06.44.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 Apr 2022 06:44:55 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) client-ip=2620:137:e000::1:18; Authentication-Results: mx.google.com; dkim=pass header.i=@linuxfoundation.org header.s=korg header.b=a0Peh79g; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 3F2185732D2; Wed, 6 Apr 2022 04:32:19 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1836556AbiDFAgi (ORCPT + 99 others); Tue, 5 Apr 2022 20:36:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36674 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S240485AbiDEKfq (ORCPT ); Tue, 5 Apr 2022 06:35:46 -0400 Received: from dfw.source.kernel.org (dfw.source.kernel.org [139.178.84.217]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id BAE2253A5D; Tue, 5 Apr 2022 03:21:45 -0700 (PDT) Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dfw.source.kernel.org (Postfix) with ESMTPS id 5551261562; Tue, 5 Apr 2022 10:21:45 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5F77EC385A1; Tue, 5 Apr 2022 10:21:44 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1649154104; bh=uVvsxXcsuV/zpwAblQs5D1i0APRLwni14f7UeSMlovg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=a0Peh79gjGe01tC1tKD7/PePKpdoZ+42F4G0NV5kZmHS1fbUOtxmKt/JQ35iZOjpF arUJ8vdx2dWfHJk1WE9Na1loSbUwZUYqnyJb4utVF1AGK8fyKhsa+rI+vi3GRyKQTo tLa254vaiiKSZ9iDk6FehfUbG1rXMH5p3SdqrK8I= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Akira Kawata , kernel test robot , Kees Cook , Sasha Levin Subject: [PATCH 5.10 460/599] fs/binfmt_elf: Fix AT_PHDR for unusual ELF files Date: Tue, 5 Apr 2022 09:32:34 +0200 Message-Id: <20220405070312.518246120@linuxfoundation.org> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220405070258.802373272@linuxfoundation.org> References: <20220405070258.802373272@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Akira Kawata [ Upstream commit 0da1d5002745cdc721bc018b582a8a9704d56c42 ] BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=197921 As pointed out in the discussion of buglink, we cannot calculate AT_PHDR as the sum of load_addr and exec->e_phoff. : The AT_PHDR of ELF auxiliary vectors should point to the memory address : of program header. But binfmt_elf.c calculates this address as follows: : : NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); : : which is wrong since e_phoff is the file offset of program header and : load_addr is the memory base address from PT_LOAD entry. : : The ld.so uses AT_PHDR as the memory address of program header. In normal : case, since the e_phoff is usually 64 and in the first PT_LOAD region, it : is the correct program header address. : : But if the address of program header isn't equal to the first PT_LOAD : address + e_phoff (e.g. Put the program header in other non-consecutive : PT_LOAD region), ld.so will try to read program header from wrong address : then crash or use incorrect program header. This is because exec->e_phoff is the offset of PHDRs in the file and the address of PHDRs in the memory may differ from it. This patch fixes the bug by calculating the address of program headers from PT_LOADs directly. Signed-off-by: Akira Kawata Reported-by: kernel test robot Acked-by: Kees Cook Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220127124014.338760-2-akirakawata1@gmail.com Signed-off-by: Sasha Levin --- fs/binfmt_elf.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 04c4aa7a1df2..ed507d27034b 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -170,8 +170,8 @@ static int padzero(unsigned long elf_bss) static int create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, - unsigned long load_addr, unsigned long interp_load_addr, - unsigned long e_entry) + unsigned long interp_load_addr, + unsigned long e_entry, unsigned long phdr_addr) { struct mm_struct *mm = current->mm; unsigned long p = bprm->p; @@ -256,7 +256,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec, NEW_AUX_ENT(AT_HWCAP, ELF_HWCAP); NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); - NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); + NEW_AUX_ENT(AT_PHDR, phdr_addr); NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr)); NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); NEW_AUX_ENT(AT_BASE, interp_load_addr); @@ -820,7 +820,7 @@ static int parse_elf_properties(struct file *f, const struct elf_phdr *phdr, static int load_elf_binary(struct linux_binprm *bprm) { struct file *interpreter = NULL; /* to shut gcc up */ - unsigned long load_addr = 0, load_bias = 0; + unsigned long load_addr, load_bias = 0, phdr_addr = 0; int load_addr_set = 0; unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata = NULL; @@ -1153,6 +1153,17 @@ static int load_elf_binary(struct linux_binprm *bprm) reloc_func_desc = load_bias; } } + + /* + * Figure out which segment in the file contains the Program + * Header table, and map to the associated memory address. + */ + if (elf_ppnt->p_offset <= elf_ex->e_phoff && + elf_ex->e_phoff < elf_ppnt->p_offset + elf_ppnt->p_filesz) { + phdr_addr = elf_ex->e_phoff - elf_ppnt->p_offset + + elf_ppnt->p_vaddr; + } + k = elf_ppnt->p_vaddr; if ((elf_ppnt->p_flags & PF_X) && k < start_code) start_code = k; @@ -1188,6 +1199,7 @@ static int load_elf_binary(struct linux_binprm *bprm) } e_entry = elf_ex->e_entry + load_bias; + phdr_addr += load_bias; elf_bss += load_bias; elf_brk += load_bias; start_code += load_bias; @@ -1251,8 +1263,8 @@ static int load_elf_binary(struct linux_binprm *bprm) goto out; #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */ - retval = create_elf_tables(bprm, elf_ex, - load_addr, interp_load_addr, e_entry); + retval = create_elf_tables(bprm, elf_ex, interp_load_addr, + e_entry, phdr_addr); if (retval < 0) goto out; -- 2.34.1