Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Oct 2015 11:32:39 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r290099 - stable/10/libexec/rtld-elf
Message-ID:  <201510281132.t9SBWdPw033904@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Wed Oct 28 11:32:39 2015
New Revision: 290099
URL: https://svnweb.freebsd.org/changeset/base/290099

Log:
  MFC r289324:
  Allow PT_NOTES segments to be located anywhere in the executable
  image.

Modified:
  stable/10/libexec/rtld-elf/map_object.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/libexec/rtld-elf/map_object.c
==============================================================================
--- stable/10/libexec/rtld-elf/map_object.c	Wed Oct 28 11:29:58 2015	(r290098)
+++ stable/10/libexec/rtld-elf/map_object.c	Wed Oct 28 11:32:39 2015	(r290099)
@@ -88,6 +88,8 @@ map_object(int fd, const char *path, con
     size_t relro_size;
     Elf_Addr note_start;
     Elf_Addr note_end;
+    char *note_map;
+    size_t note_map_len;
 
     hdr = get_elf_header(fd, path);
     if (hdr == NULL)
@@ -108,6 +110,7 @@ map_object(int fd, const char *path, con
     relro_size = 0;
     note_start = 0;
     note_end = 0;
+    note_map = NULL;
     segs = alloca(sizeof(segs[0]) * hdr->e_phnum);
     stack_flags = RTLD_DEFAULT_STACK_PF_EXEC | PF_R | PF_W;
     while (phdr < phlimit) {
@@ -150,9 +153,20 @@ map_object(int fd, const char *path, con
 
 	case PT_NOTE:
 	    if (phdr->p_offset > PAGE_SIZE ||
-	      phdr->p_offset + phdr->p_filesz > PAGE_SIZE)
-		break;
-	    note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
+	      phdr->p_offset + phdr->p_filesz > PAGE_SIZE) {
+		note_map_len = round_page(phdr->p_offset +
+		  phdr->p_filesz) - trunc_page(phdr->p_offset);
+		note_map = mmap(NULL, note_map_len, PROT_READ,
+		  MAP_PRIVATE, fd, trunc_page(phdr->p_offset));
+		if (note_map == MAP_FAILED) {
+		    _rtld_error("%s: error mapping PT_NOTE (%d)", path, errno);
+		    goto error;
+		}
+		note_start = (Elf_Addr)(note_map + phdr->p_offset -
+		  trunc_page(phdr->p_offset));
+	    } else {
+		note_start = (Elf_Addr)(char *)hdr + phdr->p_offset;
+	    }
 	    note_end = note_start + phdr->p_filesz;
 	    break;
 	}
@@ -295,12 +309,16 @@ map_object(int fd, const char *path, con
     obj->relro_size = round_page(relro_size);
     if (note_start < note_end)
 	digest_notes(obj, note_start, note_end);
+    if (note_map != NULL)
+	munmap(note_map, note_map_len);
     munmap(hdr, PAGE_SIZE);
     return (obj);
 
 error1:
     munmap(mapbase, mapsize);
 error:
+    if (note_map != NULL && note_map != MAP_FAILED)
+	munmap(note_map, note_map_len);
     munmap(hdr, PAGE_SIZE);
     return (NULL);
 }



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