public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: linux-kernel@vger.kernel.org, stable@vger.kernel.org
Cc: Akira Kawata <akirakawata1@gmail.com>,
	kernel test robot <lkp@intel.com>,
	Kees Cook <keescook@chromium.org>,
	Sasha Levin <sashal@kernel.org>,
	viro@zeniv.linux.org.uk, linux-fsdevel@vger.kernel.org,
	linux-mm@kvack.org
Subject: [PATCH AUTOSEL 5.10 12/21] fs/binfmt_elf: Fix AT_PHDR for unusual ELF files
Date: Mon, 28 Mar 2022 07:22:45 -0400	[thread overview]
Message-ID: <20220328112254.1556286-12-sashal@kernel.org> (raw)
In-Reply-To: <20220328112254.1556286-1-sashal@kernel.org>

From: Akira Kawata <akirakawata1@gmail.com>

[ 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 <akirakawata1@gmail.com>
Reported-by: kernel test robot <lkp@intel.com>
Acked-by: Kees Cook <keescook@chromium.org>
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20220127124014.338760-2-akirakawata1@gmail.com
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 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


  parent reply	other threads:[~2022-03-28 11:24 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-03-28 11:22 [PATCH AUTOSEL 5.10 01/21] LSM: general protection fault in legacy_parse_param Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 02/21] regulator: rpi-panel: Handle I2C errors/timing to the Atmel Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 03/21] gcc-plugins/stackleak: Exactly match strings instead of prefixes Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 04/21] pinctrl: npcm: Fix broken references to chip->parent_device Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 05/21] block, bfq: don't move oom_bfqq Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 06/21] selinux: use correct type for context length Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 07/21] selinux: allow FIOCLEX and FIONCLEX with policy capability Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 08/21] loop: use sysfs_emit() in the sysfs xxx show() Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 09/21] Fix incorrect type in assignment of ipv6 port for audit Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 10/21] irqchip/qcom-pdc: Fix broken locking Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 11/21] irqchip/nvic: Release nvic_base upon failure Sasha Levin
2022-03-28 11:22 ` Sasha Levin [this message]
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 13/21] bfq: fix use-after-free in bfq_dispatch_request Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 14/21] ACPICA: Avoid walking the ACPI Namespace if it is not there Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 15/21] lib/raid6/test/Makefile: Use $(pound) instead of \# for Make 4.3 Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 16/21] Revert "Revert "block, bfq: honor already-setup queue merges"" Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 17/21] ACPI/APEI: Limit printable size of BERT table data Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 18/21] PM: core: keep irq flags in device_pm_check_callbacks() Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 19/21] parisc: Fix handling off probe non-access faults Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 20/21] nvme-tcp: lockdep: annotate in-kernel sockets Sasha Levin
2022-03-28 11:22 ` [PATCH AUTOSEL 5.10 21/21] spi: tegra20: Use of_device_get_match_data() Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220328112254.1556286-12-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=akirakawata1@gmail.com \
    --cc=keescook@chromium.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=lkp@intel.com \
    --cc=stable@vger.kernel.org \
    --cc=viro@zeniv.linux.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox