Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 18 Oct 2009 12:57:49 +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: r198202 - head/sys/kern
Message-ID:  <200910181257.n9ICvn3R069352@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Oct 18 12:57:48 2009
New Revision: 198202
URL: http://svn.freebsd.org/changeset/base/198202

Log:
  If ET_DYN binary has non-zero base address for some reason, honour it
  and do not relocate the binary to ET_DYN_LOAD_ADDR. This allows for the
  binary author to influence address map of the process. In particular,
  when the binary is actually an interpeter, this allows to have almost
  usual process address map.
  
  Communicate the relocation bias of the mapping for interpeter-less
  ET_DYN binary, that is interperter itself, in AT_BASE aux entry. This
  way, rtld is able to find its dynamic structure and relocate itself.
  Note that mapbase in the rtld is still wrong and requires further
  fixing.
  
  Reported and tested by:	rwatson
  Discussed with:	kan
  MFC after:	3 days

Modified:
  head/sys/kern/imgact_elf.c

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Sun Oct 18 12:55:39 2009	(r198201)
+++ head/sys/kern/imgact_elf.c	Sun Oct 18 12:57:48 2009	(r198202)
@@ -688,9 +688,9 @@ __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, et_dyn_addr, entry = 0, proghdr = 0;
+	u_long addr, baddr, et_dyn_addr, entry = 0, proghdr = 0;
 	int32_t osrel = 0;
-	int error = 0, i;
+	int error = 0, i, n;
 	const char *interp = NULL, *newinterp = NULL;
 	Elf_Brandinfo *brand_info;
 	char *path;
@@ -719,14 +719,22 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 	phdr = (const Elf_Phdr *)(imgp->image_header + hdr->e_phoff);
 	if (!aligned(phdr, Elf_Addr))
 		return (ENOEXEC);
+	n = 0;
+	baddr = 0;
 	for (i = 0; i < hdr->e_phnum; i++) {
+		if (phdr[i].p_type == PT_LOAD) {
+			if (n == 0)
+				baddr = phdr[i].p_vaddr;
+			n++;
+			continue;
+		}
 		if (phdr[i].p_type == PT_INTERP) {
 			/* Path to interpreter */
 			if (phdr[i].p_filesz > MAXPATHLEN ||
 			    phdr[i].p_offset + phdr[i].p_filesz > PAGE_SIZE)
 				return (ENOEXEC);
 			interp = imgp->image_header + phdr[i].p_offset;
-			break;
+			continue;
 		}
 	}
 
@@ -739,7 +747,14 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 	if (hdr->e_type == ET_DYN) {
 		if ((brand_info->flags & BI_CAN_EXEC_DYN) == 0)
 			return (ENOEXEC);
-		et_dyn_addr = ET_DYN_LOAD_ADDR;
+		/*
+		 * Honour the base load address from the dso if it is
+		 * non-zero for some reason.
+		 */
+		if (baddr == 0)
+			et_dyn_addr = ET_DYN_LOAD_ADDR;
+		else
+			et_dyn_addr = 0;
 	} else
 		et_dyn_addr = 0;
 	sv = brand_info->sysvec;
@@ -910,7 +925,7 @@ __CONCAT(exec_, __elfN(imgact))(struct i
 			return (error);
 		}
 	} else
-		addr = 0;
+		addr = et_dyn_addr;
 
 	/*
 	 * Construct auxargs table (used by the fixup routine)



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