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

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