Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 16 Jan 2018 18:20:12 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r328052 - head/usr.sbin/kldxref
Message-ID:  <201801161820.w0GIKCNi098087@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Tue Jan 16 18:20:12 2018
New Revision: 328052
URL: https://svnweb.freebsd.org/changeset/base/328052

Log:
  kldxref: handle modules with md_cval at the end of allocated sections
  
  Attempting to retrieve an md_cval string from a kernel module with
  kldxref would throw a offset error for modules created using lld, since
  this value would be placed at the end of all allocated sections.
  
  Add an ef_read_seg_string method to the ef interface, to allow reading
  strings of varying size without attempting to read beyond the segment's
  bounds.
  
  PR:		224875
  Submitted by:	Mitchell Horne <mhorne063@gmail.com>
  Reviewed by:	cem, kib
  Sponsored by:	The FreeBSD Foundation
  Differential Revision:	https://reviews.freebsd.org/D13923

Modified:
  head/usr.sbin/kldxref/ef.c
  head/usr.sbin/kldxref/ef.h
  head/usr.sbin/kldxref/ef_obj.c
  head/usr.sbin/kldxref/kldxref.c

Modified: head/usr.sbin/kldxref/ef.c
==============================================================================
--- head/usr.sbin/kldxref/ef.c	Tue Jan 16 11:25:08 2018	(r328051)
+++ head/usr.sbin/kldxref/ef.c	Tue Jan 16 18:20:12 2018	(r328052)
@@ -90,6 +90,8 @@ static int ef_read_entry(elf_file_t ef, Elf_Off offset
 static int ef_seg_read(elf_file_t ef, Elf_Off offset, size_t len, void *dest);
 static int ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len,
     void *dest);
+static int ef_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len,
+    char *dest);
 static int ef_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len,
     void **ptr);
 static int ef_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len,
@@ -106,6 +108,7 @@ static struct elf_file_ops ef_file_ops = {
 	ef_read_entry,
 	ef_seg_read,
 	ef_seg_read_rel,
+	ef_seg_read_string,
 	ef_seg_read_entry,
 	ef_seg_read_entry_rel,
 	ef_symaddr,
@@ -494,6 +497,28 @@ ef_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t 
 		if (error != 0)
 			return (error);
 	}
+	return (0);
+}
+
+static int
+ef_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len, char *dest)
+{
+	u_long ofs = ef_get_offset(ef, offset);
+	ssize_t r;
+
+	if (ofs == 0 || ofs == (Elf_Off)-1) {
+		if (ef->ef_verbose)
+			warnx("ef_seg_read_string(%s): bad offset (%lx:%ld)",
+			    ef->ef_name, (long)offset, ofs);
+		return (EFAULT);
+	}
+
+	r = pread(ef->ef_fd, dest, len, ofs);
+	if (r < 0)
+		return (errno);
+	if (strnlen(dest, len) == len)
+		return (EFAULT);
+
 	return (0);
 }
 

Modified: head/usr.sbin/kldxref/ef.h
==============================================================================
--- head/usr.sbin/kldxref/ef.h	Tue Jan 16 11:25:08 2018	(r328051)
+++ head/usr.sbin/kldxref/ef.h	Tue Jan 16 18:20:12 2018	(r328052)
@@ -21,6 +21,8 @@
     (ef)->ef_ops->seg_read((ef)->ef_ef, offset, len, dest)
 #define EF_SEG_READ_REL(ef, offset, len, dest) \
     (ef)->ef_ops->seg_read_rel((ef)->ef_ef, offset, len, dest)
+#define EF_SEG_READ_STRING(ef, offset, len, dest) \
+    (ef)->ef_ops->seg_read_string((ef)->ef_ef, offset, len, dest)
 #define EF_SEG_READ_ENTRY(ef, offset, len, ptr) \
     (ef)->ef_ops->seg_read_entry((ef)->kf_ef, offset, len, ptr)
 #define EF_SEG_READ_ENTRY_REL(ef, offset, len, ptr) \
@@ -44,6 +46,8 @@ struct elf_file_ops {
 	int (*seg_read)(elf_file_t ef, Elf_Off offset, size_t len, void *dest);
 	int (*seg_read_rel)(elf_file_t ef, Elf_Off offset, size_t len,
 	    void *dest);
+	int (*seg_read_string)(elf_file_t, Elf_Off offset, size_t len,
+	    char *dest);
 	int (*seg_read_entry)(elf_file_t ef, Elf_Off offset, size_t len,
 	    void**ptr);
 	int (*seg_read_entry_rel)(elf_file_t ef, Elf_Off offset, size_t len,

Modified: head/usr.sbin/kldxref/ef_obj.c
==============================================================================
--- head/usr.sbin/kldxref/ef_obj.c	Tue Jan 16 11:25:08 2018	(r328051)
+++ head/usr.sbin/kldxref/ef_obj.c	Tue Jan 16 18:20:12 2018	(r328052)
@@ -110,6 +110,8 @@ static int ef_obj_seg_read(elf_file_t ef, Elf_Off offs
     void *dest);
 static int ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, size_t len,
     void *dest);
+static int ef_obj_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len,
+    char *dest);
 static int ef_obj_seg_read_entry(elf_file_t ef, Elf_Off offset, size_t len,
     void **ptr);
 static int ef_obj_seg_read_entry_rel(elf_file_t ef, Elf_Off offset, size_t len,
@@ -126,6 +128,7 @@ static struct elf_file_ops ef_obj_file_ops = {
 	ef_obj_read_entry,
 	ef_obj_seg_read,
 	ef_obj_seg_read_rel,
+	ef_obj_seg_read_string,
 	ef_obj_seg_read_entry,
 	ef_obj_seg_read_entry_rel,
 	ef_obj_symaddr,
@@ -295,6 +298,27 @@ ef_obj_seg_read_rel(elf_file_t ef, Elf_Off offset, siz
 				return (error);
 		}
 	}
+	return (0);
+}
+
+static int
+ef_obj_seg_read_string(elf_file_t ef, Elf_Off offset, size_t len, char *dest)
+{
+
+	if (offset >= ef->size) {
+		if (ef->ef_verbose)
+			warnx("ef_obj_seg_read_string(%s): bad offset (%lx)",
+			    ef->ef_name, (long)offset);
+		return (EFAULT);
+	}
+
+	if (ef->size - offset < len)
+		len = ef->size - offset;
+
+	if (strnlen(ef->address + offset, len) == len)
+		return (EFAULT);
+
+	memcpy(dest, ef->address + offset, len);
 	return (0);
 }
 

Modified: head/usr.sbin/kldxref/kldxref.c
==============================================================================
--- head/usr.sbin/kldxref/kldxref.c	Tue Jan 16 11:25:08 2018	(r328051)
+++ head/usr.sbin/kldxref/kldxref.c	Tue Jan 16 18:20:12 2018	(r328052)
@@ -571,9 +571,8 @@ read_kld(char *filename, char *kldname)
 			check(EF_SEG_READ_REL(&ef, (Elf_Off)*p, sizeof(md),
 			    &md));
 			p++;
-			check(EF_SEG_READ(&ef, (Elf_Off)md.md_cval,
+			check(EF_SEG_READ_STRING(&ef, (Elf_Off)md.md_cval,
 			    sizeof(cval), cval));
-			cval[MAXMODNAME] = '\0';
 			parse_entry(&md, cval, &ef, kldname);
 		}
 		if (error)



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