svn commit: r328052 - head/usr.sbin/kldxref
Ed Maste
emaste at FreeBSD.org
Tue Jan 16 18:20:13 UTC 2018
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 at 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)
More information about the svn-src-all
mailing list