Blame SOURCES/0013-elflink-Fix-program-header-address-calculation.patch

fc9b0e
From 9fe6594da91e86280c9d71877a91cee83aaedae6 Mon Sep 17 00:00:00 2001
fc9b0e
Message-Id: <9fe6594da91e86280c9d71877a91cee83aaedae6.1566225007.git.aquini@redhat.com>
fc9b0e
In-Reply-To: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
fc9b0e
References: <d42f467a923dfc09309acb7a83b42e3285fbd8f4.1566225007.git.aquini@redhat.com>
fc9b0e
From: Sandipan Das <sandipan@linux.ibm.com>
fc9b0e
Date: Wed, 12 Jun 2019 12:34:30 +0530
fc9b0e
Subject: [RHEL7 PATCH 13/31] elflink: Fix program header address calculation
fc9b0e
fc9b0e
This fixes the virtual address calculation for the ELF program
fc9b0e
header. Based on the man page of dl_iterate_phdr(), the location
fc9b0e
of a particular program header in virtual memory should be the
fc9b0e
sum of the base address of the shared object and the segment's
fc9b0e
virtual address.
fc9b0e
fc9b0e
Signed-off-by: Sandipan Das <sandipan@linux.ibm.com>
fc9b0e
Signed-off-by: Eric B Munson <emunson@mgebm.net>
fc9b0e
Signed-off-by: Rafael Aquini <aquini@redhat.com>
fc9b0e
---
fc9b0e
 elflink.c | 40 ++++++++++++++++++++++++----------------
fc9b0e
 1 file changed, 24 insertions(+), 16 deletions(-)
fc9b0e
fc9b0e
diff --git a/elflink.c b/elflink.c
fc9b0e
index ffc84dd..1150bde 100644
fc9b0e
--- a/elflink.c
fc9b0e
+++ b/elflink.c
fc9b0e
@@ -374,7 +374,8 @@ static int get_shared_file_name(struct seg_info *htlb_seg_info, char *file_path)
fc9b0e
 }
fc9b0e
 
fc9b0e
 /* Find the .dynamic program header */
fc9b0e
-static int find_dynamic(Elf_Dyn **dyntab, const Elf_Phdr *phdr, int phnum)
fc9b0e
+static int find_dynamic(Elf_Dyn **dyntab, const ElfW(Addr) addr,
fc9b0e
+			const Elf_Phdr *phdr, int phnum)
fc9b0e
 {
fc9b0e
 	int i = 1;
fc9b0e
 
fc9b0e
@@ -382,7 +383,7 @@ static int find_dynamic(Elf_Dyn **dyntab, const Elf_Phdr *phdr, int phnum)
fc9b0e
 		++i;
fc9b0e
 	}
fc9b0e
 	if (phdr[i].p_type == PT_DYNAMIC) {
fc9b0e
-		*dyntab = (Elf_Dyn *)phdr[i].p_vaddr;
fc9b0e
+		*dyntab = (Elf_Dyn *)(addr + phdr[i].p_vaddr);
fc9b0e
 		return 0;
fc9b0e
 	} else {
fc9b0e
 		DEBUG("No dynamic segment found\n");
fc9b0e
@@ -473,7 +474,8 @@ ElfW(Word) __attribute__ ((weak)) plt_extrasz(ElfW(Dyn) *dyntab)
fc9b0e
  * include these initialized variables in our copy.
fc9b0e
  */
fc9b0e
 
fc9b0e
-static void get_extracopy(struct seg_info *seg, const Elf_Phdr *phdr, int phnum)
fc9b0e
+static void get_extracopy(struct seg_info *seg, const ElfW(Addr) addr,
fc9b0e
+			  const Elf_Phdr *phdr, int phnum)
fc9b0e
 {
fc9b0e
 	Elf_Dyn *dyntab;        /* dynamic segment table */
fc9b0e
 	Elf_Sym *symtab = NULL; /* dynamic symbol table */
fc9b0e
@@ -492,7 +494,7 @@ static void get_extracopy(struct seg_info *seg, const Elf_Phdr *phdr, int phnum)
fc9b0e
 		goto bail2;
fc9b0e
 
fc9b0e
 	/* Find dynamic program header */
fc9b0e
-	ret = find_dynamic(&dyntab, phdr, phnum);
fc9b0e
+	ret = find_dynamic(&dyntab, addr, phdr, phnum);
fc9b0e
 	if (ret < 0)
fc9b0e
 		goto bail;
fc9b0e
 
fc9b0e
@@ -608,7 +610,8 @@ static unsigned long hugetlb_prev_slice_end(unsigned long addr)
fc9b0e
 /*
fc9b0e
  * Store a copy of the given program header
fc9b0e
  */
fc9b0e
-static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
fc9b0e
+static int save_phdr(int table_idx, int phnum, const ElfW(Addr) addr,
fc9b0e
+		     const ElfW(Phdr) *phdr)
fc9b0e
 {
fc9b0e
 	int prot = 0;
fc9b0e
 
fc9b0e
@@ -626,7 +629,7 @@ static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
fc9b0e
 	if (phdr->p_flags & PF_X)
fc9b0e
 		prot |= PROT_EXEC;
fc9b0e
 
fc9b0e
-	htlb_seg_table[table_idx].vaddr = (void *) phdr->p_vaddr;
fc9b0e
+	htlb_seg_table[table_idx].vaddr = (void *)(addr + phdr->p_vaddr);
fc9b0e
 	htlb_seg_table[table_idx].filesz = phdr->p_filesz;
fc9b0e
 	htlb_seg_table[table_idx].memsz = phdr->p_memsz;
fc9b0e
 	htlb_seg_table[table_idx].prot = prot;
fc9b0e
@@ -634,8 +637,8 @@ static int save_phdr(int table_idx, int phnum, const ElfW(Phdr) *phdr)
fc9b0e
 
fc9b0e
 	INFO("Segment %d (phdr %d): %#0lx-%#0lx  (filesz=%#0lx) "
fc9b0e
 		"(prot = %#0x)\n", table_idx, phnum,
fc9b0e
-		(unsigned long)  phdr->p_vaddr,
fc9b0e
-		(unsigned long) phdr->p_vaddr + phdr->p_memsz,
fc9b0e
+		(unsigned long) addr + phdr->p_vaddr,
fc9b0e
+		(unsigned long) addr + phdr->p_vaddr + phdr->p_memsz,
fc9b0e
 		(unsigned long) phdr->p_filesz, (unsigned int) prot);
fc9b0e
 
fc9b0e
 	return 0;
fc9b0e
@@ -718,16 +721,19 @@ int parse_elf_normal(struct dl_phdr_info *info, size_t size, void *data)
fc9b0e
 
fc9b0e
 		seg_psize = segment_requested_page_size(&info->dlpi_phdr[i]);
fc9b0e
 		if (seg_psize != page_size) {
fc9b0e
-			if (save_phdr(htlb_num_segs, i, &info->dlpi_phdr[i]))
fc9b0e
+			if (save_phdr(htlb_num_segs, i, info->dlpi_addr,
fc9b0e
+				      &info->dlpi_phdr[i]))
fc9b0e
 				return 1;
fc9b0e
 			get_extracopy(&htlb_seg_table[htlb_num_segs],
fc9b0e
-					&info->dlpi_phdr[0], info->dlpi_phnum);
fc9b0e
+				      info->dlpi_addr, info->dlpi_phdr,
fc9b0e
+				      info->dlpi_phnum);
fc9b0e
 			htlb_seg_table[htlb_num_segs].page_size = seg_psize;
fc9b0e
 			htlb_num_segs++;
fc9b0e
 		}
fc9b0e
-		start = ALIGN_DOWN(info->dlpi_phdr[i].p_vaddr, seg_psize);
fc9b0e
-		end = ALIGN(info->dlpi_phdr[i].p_vaddr +
fc9b0e
-				info->dlpi_phdr[i].p_memsz, seg_psize);
fc9b0e
+		start = ALIGN_DOWN(info->dlpi_addr +
fc9b0e
+				   info->dlpi_phdr[i].p_vaddr, seg_psize);
fc9b0e
+		end = ALIGN(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr +
fc9b0e
+			    info->dlpi_phdr[i].p_memsz, seg_psize);
fc9b0e
 
fc9b0e
 		segments[num_segs].page_size = seg_psize;
fc9b0e
 		segments[num_segs].start = start;
fc9b0e
@@ -771,8 +777,9 @@ int parse_elf_partial(struct dl_phdr_info *info, size_t size, void *data)
fc9b0e
 		 * in this forced way won't violate any contiguity
fc9b0e
 		 * constraints.
fc9b0e
 		 */
fc9b0e
-		vaddr = hugetlb_next_slice_start(info->dlpi_phdr[i].p_vaddr);
fc9b0e
-		gap = vaddr - info->dlpi_phdr[i].p_vaddr;
fc9b0e
+		vaddr = hugetlb_next_slice_start(info->dlpi_addr +
fc9b0e
+						 info->dlpi_phdr[i].p_vaddr);
fc9b0e
+		gap = vaddr - (info->dlpi_addr + info->dlpi_phdr[i].p_vaddr);
fc9b0e
 		slice_end = hugetlb_slice_end(vaddr);
fc9b0e
 		/*
fc9b0e
 		 * we should stop remapping just before the slice
fc9b0e
@@ -795,7 +802,8 @@ int parse_elf_partial(struct dl_phdr_info *info, size_t size, void *data)
fc9b0e
 		}
fc9b0e
 		memsz = hugetlb_prev_slice_end(vaddr + memsz) - vaddr;
fc9b0e
 
fc9b0e
-		if (save_phdr(htlb_num_segs, i, &info->dlpi_phdr[i]))
fc9b0e
+		if (save_phdr(htlb_num_segs, i, info->dlpi_addr,
fc9b0e
+			      &info->dlpi_phdr[i]))
fc9b0e
 			return 1;
fc9b0e
 
fc9b0e
 		/*
fc9b0e
-- 
fc9b0e
1.8.3.1
fc9b0e