Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Oct 2009 15:33:01 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197934 - head/sys/kern
Message-ID:  <200910101533.n9AFX1Gq085870@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sat Oct 10 15:33:01 2009
New Revision: 197934
URL: http://svn.freebsd.org/changeset/base/197934

Log:
  Map PIE binaries at non-zero base address.
  
  Discussed with:	bz
  Reviewed by:	kan
  Tested by:	bz (i386, amd64), bsam (linux)
  MFC after:	some time

Modified:
  head/sys/kern/imgact_elf.c

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Sat Oct 10 15:31:24 2009	(r197933)
+++ head/sys/kern/imgact_elf.c	Sat Oct 10 15:33:01 2009	(r197934)
@@ -688,7 +688,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 	u_long text_size = 0, data_size = 0, total_size = 0;
 	u_long text_addr = 0, data_addr = 0;
 	u_long seg_size, seg_addr;
-	u_long addr, entry = 0, proghdr = 0;
+	u_long addr, et_dyn_addr, entry = 0, proghdr = 0;
 	int32_t osrel = 0;
 	int error = 0, i;
 	const char *interp = NULL, *newinterp = NULL;
@@ -736,9 +736,12 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 		    hdr->e_ident[EI_OSABI]);
 		return (ENOEXEC);
 	}
-	if (hdr->e_type == ET_DYN &&
-	    (brand_info->flags & BI_CAN_EXEC_DYN) == 0)
-		return (ENOEXEC);
+	if (hdr->e_type == ET_DYN) {
+		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
+			return (ENOEXEC);
+		et_dyn_addr = ET_DYN_LOAD_ADDR;
+	} else
+		et_dyn_addr = 0;
 	sv = brand_info->sysvec;
 	if (interp != NULL && brand_info->interp_newpath != NULL)
 		newinterp = brand_info->interp_newpath;
@@ -786,7 +789,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 
 			if ((error = __elfN(load_section)(vmspace,
 			    imgp->object, phdr[i].p_offset,
-			    (caddr_t)(uintptr_t)phdr[i].p_vaddr,
+			    (caddr_t)(uintptr_t)phdr[i].p_vaddr + et_dyn_addr,
 			    phdr[i].p_memsz, phdr[i].p_filesz, prot,
 			    sv->sv_pagesize)) != 0)
 				return (error);
@@ -800,11 +803,12 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 			if (phdr[i].p_offset == 0 &&
 			    hdr->e_phoff + hdr->e_phnum * hdr->e_phentsize
 				<= phdr[i].p_filesz)
-				proghdr = phdr[i].p_vaddr + hdr->e_phoff;
+				proghdr = phdr[i].p_vaddr + hdr->e_phoff +
+				    et_dyn_addr;
 
-			seg_addr = trunc_page(phdr[i].p_vaddr);
+			seg_addr = trunc_page(phdr[i].p_vaddr + et_dyn_addr);
 			seg_size = round_page(phdr[i].p_memsz +
-			    phdr[i].p_vaddr - seg_addr);
+			    phdr[i].p_vaddr + et_dyn_addr - seg_addr);
 
 			/*
 			 * Is this .text or .data?  We can't use
@@ -826,7 +830,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 			    phdr[i].p_memsz)) {
 				text_size = seg_size;
 				text_addr = seg_addr;
-				entry = (u_long)hdr->e_entry;
+				entry = (u_long)hdr->e_entry + et_dyn_addr;
 			} else {
 				data_size = seg_size;
 				data_addr = seg_addr;
@@ -834,7 +838,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 			total_size += seg_size;
 			break;
 		case PT_PHDR: 	/* Program header table info */
-			proghdr = phdr[i].p_vaddr;
+			proghdr = phdr[i].p_vaddr + et_dyn_addr;
 			break;
 		default:
 			break;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910101533.n9AFX1Gq085870>