Author: emaste
Date: Tue Feb 13 22:40:33 2018
New Revision: 329247
URL: https://svnweb.freebsd.org/changeset/base/329247

Log:
  MFC r328052: kldxref: handle modules with md_cval at end of allocated secs
  
  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 <mhorne...@gmail.com>
  Sponsored by: The FreeBSD Foundation

Modified:
  stable/11/usr.sbin/kldxref/ef.c
  stable/11/usr.sbin/kldxref/ef.h
  stable/11/usr.sbin/kldxref/ef_obj.c
  stable/11/usr.sbin/kldxref/kldxref.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/kldxref/ef.c
==============================================================================
--- stable/11/usr.sbin/kldxref/ef.c     Tue Feb 13 22:37:54 2018        
(r329246)
+++ stable/11/usr.sbin/kldxref/ef.c     Tue Feb 13 22:40:33 2018        
(r329247)
@@ -88,6 +88,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,
@@ -104,6 +106,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,
@@ -492,6 +495,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: stable/11/usr.sbin/kldxref/ef.h
==============================================================================
--- stable/11/usr.sbin/kldxref/ef.h     Tue Feb 13 22:37:54 2018        
(r329246)
+++ stable/11/usr.sbin/kldxref/ef.h     Tue Feb 13 22:40:33 2018        
(r329247)
@@ -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: stable/11/usr.sbin/kldxref/ef_obj.c
==============================================================================
--- stable/11/usr.sbin/kldxref/ef_obj.c Tue Feb 13 22:37:54 2018        
(r329246)
+++ stable/11/usr.sbin/kldxref/ef_obj.c Tue Feb 13 22:40:33 2018        
(r329247)
@@ -108,6 +108,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,
@@ -124,6 +126,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,
@@ -293,6 +296,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: stable/11/usr.sbin/kldxref/kldxref.c
==============================================================================
--- stable/11/usr.sbin/kldxref/kldxref.c        Tue Feb 13 22:37:54 2018        
(r329246)
+++ stable/11/usr.sbin/kldxref/kldxref.c        Tue Feb 13 22:40:33 2018        
(r329247)
@@ -569,9 +569,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)
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to