Date: Tue, 13 Feb 2018 22:40:33 +0000 (UTC) From: Ed Maste <emaste@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r329247 - stable/11/usr.sbin/kldxref Message-ID: <201802132240.w1DMeX2m051789@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 <mhorne063@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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201802132240.w1DMeX2m051789>