Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Mar 2017 13:51:13 +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: r315157 - head/sys/kern
Message-ID:  <201703121351.v2CDpDWe070986@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Mar 12 13:51:13 2017
New Revision: 315157
URL: https://svnweb.freebsd.org/changeset/base/315157

Log:
  Accept linkers representation for ELF segments with zero on-disk length.
  
  For such segments, GNU bfd linker writes knowingly incorrect value
  into the the file offset field of the program header entry, with the
  motivation that file should not be mapped for creation of this segment
  at all.
  
  Relax checks for the ELF structure validity when on-disk segment
  length is zero, and explicitely set mapping length to zero for such
  segments to avoid validating rounding arithmetic.
  
  PR:	217610
  Reported by:	Robert Clausecker <fuz@fuz.su>
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/kern/imgact_elf.c

Modified: head/sys/kern/imgact_elf.c
==============================================================================
--- head/sys/kern/imgact_elf.c	Sun Mar 12 13:49:42 2017	(r315156)
+++ head/sys/kern/imgact_elf.c	Sun Mar 12 13:51:13 2017	(r315157)
@@ -522,7 +522,8 @@ __elfN(load_section)(struct image_params
 	 * While I'm here, might as well check for something else that
 	 * is invalid: filsz cannot be greater than memsz.
 	 */
-	if ((off_t)filsz + offset > imgp->attr->va_size || filsz > memsz) {
+	if ((filsz != 0 && (off_t)filsz + offset > imgp->attr->va_size) ||
+	    filsz > memsz) {
 		uprintf("elf_load_section: truncated ELF file\n");
 		return (ENOEXEC);
 	}
@@ -538,7 +539,9 @@ __elfN(load_section)(struct image_params
 	 * early and copy the initialized data into that first page.  We
 	 * choose the second.
 	 */
-	if (memsz > filsz)
+	if (filsz == 0)
+		map_len = 0;
+	else if (memsz > filsz)
 		map_len = trunc_page_ps(offset + filsz, pagesize) - file_addr;
 	else
 		map_len = round_page_ps(offset + filsz, pagesize) - file_addr;
@@ -570,7 +573,8 @@ __elfN(load_section)(struct image_params
 	 * segment in the file is extended to provide bss.  It's a neat idea
 	 * to try and save a page, but it's a pain in the behind to implement.
 	 */
-	copy_len = (offset + filsz) - trunc_page_ps(offset + filsz, pagesize);
+	copy_len = filsz == 0 ? 0 : (offset + filsz) - trunc_page_ps(offset +
+	    filsz, pagesize);
 	map_addr = trunc_page_ps((vm_offset_t)vmaddr + filsz, pagesize);
 	map_len = round_page_ps((vm_offset_t)vmaddr + memsz, pagesize) -
 	    map_addr;



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