summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorSunil Nimmagadda <sunil@cvs.openbsd.org>2019-04-16 06:09:53 +0000
committerSunil Nimmagadda <sunil@cvs.openbsd.org>2019-04-16 06:09:53 +0000
commit181c8f2567e5d5e3acc84dbf2b07ea167c0c0e3e (patch)
tree371ef7db05dcac2df56ce3088205ed4c4414ca6c /usr.sbin
parentd67c1561e6dcace59a295625d39e096ba0fc58f8 (diff)
Rewrite using libelf(3).
Lots of help with build/tests on sparc64 from jsg@, thank you. ok deraadt
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/rdsetroot/Makefile6
-rw-r--r--usr.sbin/rdsetroot/elf32.c3
-rw-r--r--usr.sbin/rdsetroot/elf64.c3
-rw-r--r--usr.sbin/rdsetroot/elfrd_size.c396
-rw-r--r--usr.sbin/rdsetroot/rdsetroot.c259
-rw-r--r--usr.sbin/rdsetroot/rdsetroot.h13
6 files changed, 181 insertions, 499 deletions
diff --git a/usr.sbin/rdsetroot/Makefile b/usr.sbin/rdsetroot/Makefile
index eb9059ab556..2278f738c2a 100644
--- a/usr.sbin/rdsetroot/Makefile
+++ b/usr.sbin/rdsetroot/Makefile
@@ -1,7 +1,9 @@
-# $OpenBSD: Makefile,v 1.1 2019/04/05 21:07:11 deraadt Exp $
+# $OpenBSD: Makefile,v 1.2 2019/04/16 06:09:52 sunil Exp $
PROG= rdsetroot
MAN= rdsetroot.8
-SRCS= rdsetroot.c elf32.c elf64.c
+
+LDADD+= -lelf
+DPADD+= ${LIBELF}
.include <bsd.prog.mk>
diff --git a/usr.sbin/rdsetroot/elf32.c b/usr.sbin/rdsetroot/elf32.c
deleted file mode 100644
index 4b303b5135f..00000000000
--- a/usr.sbin/rdsetroot/elf32.c
+++ /dev/null
@@ -1,3 +0,0 @@
-/* $OpenBSD: elf32.c,v 1.1 2019/04/05 21:07:11 deraadt Exp $ */
-#define ELFSIZE 32
-#include "elfrd_size.c"
diff --git a/usr.sbin/rdsetroot/elf64.c b/usr.sbin/rdsetroot/elf64.c
deleted file mode 100644
index 3f453fd586e..00000000000
--- a/usr.sbin/rdsetroot/elf64.c
+++ /dev/null
@@ -1,3 +0,0 @@
-/* $OpenBSD: elf64.c,v 1.1 2019/04/05 21:07:11 deraadt Exp $ */
-#define ELFSIZE 64
-#include "elfrd_size.c"
diff --git a/usr.sbin/rdsetroot/elfrd_size.c b/usr.sbin/rdsetroot/elfrd_size.c
deleted file mode 100644
index 1a9755990c4..00000000000
--- a/usr.sbin/rdsetroot/elfrd_size.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/* $OpenBSD: elfrd_size.c,v 1.1 2019/04/05 21:07:11 deraadt Exp $ */
-
-/*
- * Copyright (c) 1994 Gordon W. Ross
- * Copyright (c) 1997 Per Fogelstrom. (ELF modifications)
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include <elf.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <nlist.h>
-#include <err.h>
-
-#include <errno.h>
-#include <limits.h>
-
-#include "rdsetroot.h"
-
-void
-ELFNAME(locate_image)(int, struct elfhdr *, char *, long *, long *, off_t *,
- size_t *);
-int
-ELFNAME(find_rd_root_image)(char *, int, Elf_Phdr *, int, long *, long *,
- off_t *, size_t *);
-int
-ELFNAME(nlist)(int, struct nlist *);
-
-struct elf_fn ELFDEFNNAME(fn) =
-{
- ELFNAME(locate_image),
- ELFNAME(find_rd_root_image)
-};
-
-void
-ELFNAME(locate_image)(int fd, struct elfhdr *ghead, char *file,
- long *prd_root_size_off, long *prd_root_image_off, off_t *pmmap_off,
- size_t *pmmap_size)
-{
- int n;
- int found = 0;
- size_t phsize;
- Elf_Ehdr head;
-
- Elf_Phdr *ph;
-
- /* elfhdr may not have the full header? */
- lseek(fd, 0, SEEK_SET);
-
- if (read(fd, &head, sizeof(head)) != sizeof(head))
- err(1, "can't read phdr area");
-
- phsize = head.e_phnum * sizeof(Elf_Phdr);
- if ((ph = malloc(phsize)) == NULL)
- err(1, "malloc");
-
- lseek(fd, head.e_phoff, SEEK_SET);
-
- if (read(fd, ph, phsize) != phsize)
- err(1, "can't read phdr area");
-
- for (n = 0; n < head.e_phnum && !found; n++) {
- if (ph[n].p_type == PT_LOAD)
- found = ELFNAME(find_rd_root_image)(file, fd, &ph[n],
- n, prd_root_size_off, prd_root_image_off,
- pmmap_off, pmmap_size);
- }
- if (!found)
- errx(1, "can't locate space for rd_root_image!");
- free(ph);
-}
-
-struct nlist ELFNAME(wantsyms)[] = {
- { "_rd_root_size", 0 },
- { "_rd_root_image", 0 },
- { NULL, 0 }
-};
-
-int
-ELFNAME(find_rd_root_image)(char *file, int fd, Elf_Phdr *ph, int segment,
- long *prd_root_size_off, long *prd_root_image_off, off_t *pmmap_off,
- size_t *pmmap_size)
-{
- unsigned long kernel_start, kernel_size;
- uint64_t rd_root_size_off, rd_root_image_off;
-
- if (ELFNAME(nlist)(fd, ELFNAME(wantsyms)))
- errx(1, "no rd_root_image symbols?");
- kernel_start = ph->p_paddr;
- kernel_size = ph->p_filesz;
-
- rd_root_size_off = ELFNAME(wantsyms)[0].n_value - kernel_start;
- if (rd_root_size_off < (ph->p_vaddr - ph->p_paddr))
- return (0);
- rd_root_size_off -= (ph->p_vaddr - ph->p_paddr);
-
- rd_root_image_off = ELFNAME(wantsyms)[1].n_value - kernel_start;
- if (rd_root_image_off < (ph->p_vaddr - ph->p_paddr))
- return (0);
- rd_root_image_off -= (ph->p_vaddr - ph->p_paddr);
-
- if (debug) {
- fprintf(stderr, "segment %d rd_root_size_off = 0x%llx\n", segment,
- rd_root_size_off);
- if ((ph->p_vaddr - ph->p_paddr) != 0)
- fprintf(stderr, "root_off v %zx p %zx, diff %zx altered %llx\n",
- (size_t)ph->p_vaddr, (size_t)ph->p_paddr,
- (size_t)(ph->p_vaddr - ph->p_paddr),
- rd_root_size_off - (ph->p_vaddr - ph->p_paddr));
- fprintf(stderr, "rd_root_image_off = 0x%llx\n", rd_root_image_off);
- }
-
- /*
- * Sanity check locations of db_* symbols
- */
- if (rd_root_image_off >= kernel_size)
- return (0);
- if (rd_root_size_off >= kernel_size)
- errx(1, "rd_root_size not in data segment?");
- *pmmap_off = ph->p_offset;
- *pmmap_size = kernel_size;
- *prd_root_size_off = rd_root_size_off;
- *prd_root_image_off = rd_root_image_off;
- return (1);
-}
-
-/*
- * __elf_is_okay__ - Determine if ehdr really
- * is ELF and valid for the target platform.
- *
- * WARNING: This is NOT a ELF ABI function and
- * as such its use should be restricted.
- */
-int
-ELFNAME(__elf_is_okay__)(Elf_Ehdr *ehdr)
-{
- int retval = 0;
- /*
- * We need to check magic, class size, endianess,
- * and version before we look at the rest of the
- * Elf_Ehdr structure. These few elements are
- * represented in a machine independent fashion.
- */
- if (IS_ELF(*ehdr) &&
- ehdr->e_ident[EI_DATA] == ELF_TARG_DATA &&
- ehdr->e_ident[EI_VERSION] == ELF_TARG_VER) {
-
-#if 0 /* allow cross, no arch check */
- /* Now check the machine dependent header */
- if (ehdr->e_machine == ELF_TARG_MACH &&
- ehdr->e_version == ELF_TARG_VER)
-#endif
- retval = 1;
- }
-
- return retval;
-}
-
-#define ISLAST(p) (p->n_name == 0 || p->n_name[0] == 0)
-#define MIN(x, y) ((x)<(y)? (x) : (y))
-
-
-int
-ELFNAME(nlist)(int fd, struct nlist *list)
-{
- struct nlist *p;
- caddr_t strtab;
- Elf_Off symoff = 0, symstroff = 0;
- Elf_Word symsize = 0;
- long symstrsize = 0;
- Elf_Sword nent, cc, i;
- Elf_Sym sbuf[1024];
- Elf_Sym *s;
- Elf_Ehdr ehdr;
- Elf_Shdr *shdr = NULL;
- size_t shdr_size;
- struct stat st;
- int usemalloc = 0;
- size_t left, len;
-
- /* Make sure obj is OK */
- if (pread(fd, &ehdr, sizeof(Elf_Ehdr), (off_t)0) != sizeof(Elf_Ehdr) ||
- !ELFNAME(__elf_is_okay__)(&ehdr) || fstat(fd, &st) < 0)
- return (-1);
-
- /* calculate section header table size */
- shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
-
- /* Make sure it's not too big to mmap */
- if (SIZE_MAX - ehdr.e_shoff < shdr_size ||
- (S_ISREG(st.st_mode) && ehdr.e_shoff + shdr_size > st.st_size)) {
- errno = EFBIG;
- return (-1);
- }
-
- /* mmap section header table */
- shdr = (Elf_Shdr *)mmap(NULL, (size_t)shdr_size, PROT_READ,
- MAP_SHARED|MAP_FILE, fd, (off_t) ehdr.e_shoff);
- if (shdr == MAP_FAILED) {
- usemalloc = 1;
- if ((shdr = malloc(shdr_size)) == NULL)
- return (-1);
-
- if (pread(fd, shdr, shdr_size, (off_t)ehdr.e_shoff) !=
- shdr_size) {
- free(shdr);
- return (-1);
- }
- }
-
- /*
- * Find the symbol table entry and its corresponding
- * string table entry. Version 1.1 of the ABI states
- * that there is only one symbol table but that this
- * could change in the future.
- */
- for (i = 0; i < ehdr.e_shnum; i++) {
- if (shdr[i].sh_type == SHT_SYMTAB) {
- if (shdr[i].sh_link >= ehdr.e_shnum)
- continue;
- symoff = shdr[i].sh_offset;
- symsize = shdr[i].sh_size;
- symstroff = shdr[shdr[i].sh_link].sh_offset;
- symstrsize = shdr[shdr[i].sh_link].sh_size;
- break;
- }
- }
-
- /* Flush the section header table */
- if (usemalloc)
- free(shdr);
- else
- munmap((caddr_t)shdr, shdr_size);
-
- /*
- * clean out any left-over information for all valid entries.
- * Type and value defined to be 0 if not found; historical
- * versions cleared other and desc as well. Also figure out
- * the largest string length so don't read any more of the
- * string table than we have to.
- *
- * XXX clearing anything other than n_type and n_value violates
- * the semantics given in the man page.
- */
- nent = 0;
- for (p = list; !ISLAST(p); ++p) {
- p->n_type = 0;
- p->n_other = 0;
- p->n_desc = 0;
- p->n_value = 0;
- ++nent;
- }
-
- /* Don't process any further if object is stripped. */
- /* ELFism - dunno if stripped by looking at header */
- if (symoff == 0)
- return nent;
-
- /* Check for files too large to mmap. */
- if (SIZE_MAX - symstrsize < symstroff ||
- (S_ISREG(st.st_mode) && symstrsize + symstroff > st.st_size)) {
- errno = EFBIG;
- return (-1);
- }
-
- /*
- * Map string table into our address space. This gives us
- * an easy way to randomly access all the strings, without
- * making the memory allocation permanent as with malloc/free
- * (i.e., munmap will return it to the system).
- */
- if (usemalloc) {
- if ((strtab = malloc(symstrsize)) == NULL)
- return (-1);
- if (pread(fd, strtab, symstrsize, (off_t)symstroff) !=
- symstrsize) {
- free(strtab);
- return (-1);
- }
- } else {
- strtab = mmap(NULL, (size_t)symstrsize, PROT_READ,
- MAP_SHARED|MAP_FILE, fd, (off_t) symstroff);
- if (strtab == MAP_FAILED)
- return (-1);
- }
-
- while (symsize >= sizeof(Elf_Sym)) {
- cc = MIN(symsize, sizeof(sbuf));
- if (pread(fd, sbuf, cc, (off_t)symoff) != cc)
- break;
- symsize -= cc;
- symoff += cc;
- for (s = sbuf; cc > 0; ++s, cc -= sizeof(*s)) {
- Elf_Word soff = s->st_name;
-
- if (soff == 0 || soff >= symstrsize)
- continue;
- left = symstrsize - soff;
-
- for (p = list; !ISLAST(p); p++) {
- char *sym;
-
- /*
- * First we check for the symbol as it was
- * provided by the user. If that fails
- * and the first char is an '_', skip over
- * the '_' and try again.
- * XXX - What do we do when the user really
- * wants '_foo' and there are symbols
- * for both 'foo' and '_foo' in the
- * table and 'foo' is first?
- */
- sym = p->n_name;
- len = strlen(sym);
-
- if ((len >= left ||
- strcmp(&strtab[soff], sym) != 0) &&
- (sym[0] != '_' || len - 1 >= left ||
- strcmp(&strtab[soff], sym + 1) != 0))
- continue;
-
- p->n_value = s->st_value;
-
- /* XXX - type conversion */
- /* is pretty rude. */
- switch (ELF_ST_TYPE(s->st_info)) {
- case STT_NOTYPE:
- switch (s->st_shndx) {
- case SHN_UNDEF:
- p->n_type = N_UNDF;
- break;
- case SHN_ABS:
- p->n_type = N_ABS;
- break;
- case SHN_COMMON:
- p->n_type = N_COMM;
- break;
- default:
- p->n_type = N_COMM | N_EXT;
- break;
- }
- break;
- case STT_OBJECT:
- p->n_type = N_DATA;
- break;
- case STT_FUNC:
- p->n_type = N_TEXT;
- break;
- case STT_FILE:
- p->n_type = N_FN;
- break;
- }
- if (ELF_ST_BIND(s->st_info) == STB_LOCAL)
- p->n_type = N_EXT;
- p->n_desc = 0;
- p->n_other = 0;
- if (--nent <= 0)
- break;
- }
- }
- }
- if (usemalloc)
- free(strtab);
- else
- munmap(strtab, symstrsize);
- return (nent);
-}
diff --git a/usr.sbin/rdsetroot/rdsetroot.c b/usr.sbin/rdsetroot/rdsetroot.c
index ef3101e3329..34fa86a7d77 100644
--- a/usr.sbin/rdsetroot/rdsetroot.c
+++ b/usr.sbin/rdsetroot/rdsetroot.c
@@ -1,79 +1,53 @@
-/* $OpenBSD: rdsetroot.c,v 1.1 2019/04/05 21:07:11 deraadt Exp $ */
+/* $OpenBSD: rdsetroot.c,v 1.2 2019/04/16 06:09:52 sunil Exp $ */
/*
- * Copyright (c) 1994 Gordon W. Ross
- * Copyright (c) 1997 Per Fogelstrom. (ELF modifications)
- * All rights reserved.
+ * Copyright (c) 2019 Sunil Nimmagadda <sunil@openbsd.org>
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/*
- * Copy a ramdisk image into the space reserved for it.
- * Kernel variables: rd_root_size, rd_root_image
- */
-
-#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
-#include <elf.h>
+#include <err.h>
#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
#include <stdio.h>
+#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
-#include <err.h>
-
-#include "rdsetroot.h"
-
-struct elfhdr head;
-
-/* Offsets relative to start of data segment. */
-long rd_root_image_off, rd_root_size_off;
-
-/* value in the location at rd_root_size_off */
-off_t rd_root_size_val;
-
-/* pointers to pieces of mapped file */
-char *dataseg;
-
-/* parameters to mmap digged out from program header */
-off_t mmap_off;
-size_t mmap_size;
+int find_rd_root_image(uint64_t *, uint64_t *, off_t *, size_t *);
+int symbol_get_u64(const char *, uint64_t *);
__dead void usage(void);
-int debug;
-
-struct elf_fn *elf_fn;
+Elf *e;
+Elf_Scn *symtab;
+size_t nsymb, strtabndx, strtabsz;
int
-main(int argc, char *argv[])
+main(int argc, char **argv)
{
- int ch, kfd, n, xflag = 0, fsfd;
- char *fs = NULL;
- char *kernel;
- u_int32_t *ip;
+ GElf_Shdr shdr;
+ Elf_Scn *scn;
+ char *dataseg, *kernel = NULL, *fs = NULL, *name;
+ off_t mmap_off, rd_root_size_val;
+ size_t shstrndx, mmap_size;
+ uint64_t rd_root_size_off, rd_root_image_off;
+ uint32_t *ip;
+ int ch, debug = 0, fsfd, kfd, n, xflag = 0;
while ((ch = getopt(argc, argv, "dx")) != -1) {
switch (ch) {
@@ -98,8 +72,7 @@ main(int argc, char *argv[])
} else
usage();
- kfd = open(kernel, xflag ? O_RDONLY : O_RDWR, 0644);
- if (kfd < 0)
+ if ((kfd = open(kernel, xflag ? O_RDONLY : O_RDWR, 0644)) < 0)
err(1, "%s", kernel);
if (fs) {
@@ -119,24 +92,59 @@ main(int argc, char *argv[])
if (pledge("stdio", NULL) == -1)
err(1, "pledge");
- n = read(kfd, &head, sizeof(head));
- if (n < sizeof(head))
- err(1, "%s: reading header", kernel);
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ errx(1, "elf_version: %s", elf_errmsg(-1));
- if (!IS_ELF(head))
- err(1, "%s: bad magic number", kernel);
+ if ((e = elf_begin(kfd, xflag ? ELF_C_READ : ELF_C_RDWR, NULL)) == NULL)
+ errx(1, "elf_begin: %s", elf_errmsg(-1));
- if (head.e_ident[EI_CLASS] == ELFCLASS32) {
- elf_fn = &ELF32_fn;
- } else if (head.e_ident[EI_CLASS] == ELFCLASS64) {
- elf_fn = &ELF64_fn;
- } else {
- fprintf(stderr, "%s: invalid elf, not 32 or 64 bit", kernel);
- exit(1);
+ if (elf_kind(e) != ELF_K_ELF)
+ errx(1, "%s: not an elf", kernel);
+
+ if (gelf_getclass(e) == ELFCLASSNONE)
+ errx(1, "%s: invalid elf, not 32 or 64 bit", kernel);
+
+ /* Retrieve index of section name string table. */
+ if (elf_getshdrstrndx(e, &shstrndx) != 0)
+ errx(1, "elf_getshdrstrndx: %s", elf_errmsg(-1));
+
+ /* Find symbol table, string table. */
+ scn = symtab = NULL;
+ while ((scn = elf_nextscn(e, scn)) != NULL) {
+ if (gelf_getshdr(scn, &shdr) != &shdr)
+ errx(1, "elf_getshdr: %s", elf_errmsg(-1));
+
+ if ((name = elf_strptr(e, shstrndx, shdr.sh_name)) == NULL)
+ errx(1, "elf_strptr: %s", elf_errmsg(-1));
+
+ if (strcmp(name, ELF_SYMTAB) == 0 &&
+ shdr.sh_type == SHT_SYMTAB && shdr.sh_entsize != 0) {
+ symtab = scn;
+ nsymb = shdr.sh_size / shdr.sh_entsize;
+ }
+
+ if (strcmp(name, ELF_STRTAB) == 0 &&
+ shdr.sh_type == SHT_STRTAB) {
+ strtabndx = elf_ndxscn(scn);
+ strtabsz = shdr.sh_size;
+ }
}
- elf_fn->locate_image(kfd, &head, kernel, &rd_root_size_off,
- &rd_root_image_off, &mmap_off, &mmap_size);
+ if (symtab == NULL)
+ errx(1, "symbol table not found");
+
+ if (strtabndx == 0)
+ errx(1, "string table not found");
+
+ if (find_rd_root_image(&rd_root_size_off, &rd_root_image_off,
+ &mmap_off, &mmap_size) != 0)
+ errx(1, "can't locate space for rd_root_image!");
+
+ if (debug) {
+ fprintf(stderr, "rd_root_size_off: 0x%llx\n", rd_root_size_off);
+ fprintf(stderr, "rd_root_image_off: 0x%llx\n",
+ rd_root_image_off);
+ }
/*
* Map in the whole data segment.
@@ -146,23 +154,19 @@ main(int argc, char *argv[])
xflag ? PROT_READ : PROT_READ | PROT_WRITE,
MAP_SHARED, kfd, mmap_off);
if (dataseg == MAP_FAILED)
- err(1, "%s: can not map data seg", kernel);
+ err(1, "%s: cannot map data seg", kernel);
/*
* Find value in the location: rd_root_size
*/
- ip = (u_int32_t *) (dataseg + rd_root_size_off);
+ ip = (uint32_t *) (dataseg + rd_root_size_off);
rd_root_size_val = *ip;
- if (debug)
+ if (debug) {
fprintf(stderr, "rd_root_size val: 0x%llx (%lld blocks)\n",
(unsigned long long)rd_root_size_val,
(unsigned long long)rd_root_size_val >> 9);
-
- /*
- * Copy the symbol table and string table.
- */
- if (debug)
fprintf(stderr, "copying root image...\n");
+ }
if (xflag) {
n = write(fsfd, dataseg + rd_root_image_off,
@@ -191,7 +195,98 @@ main(int argc, char *argv[])
if (debug)
fprintf(stderr, "...copied %d bytes\n", n);
- exit(0);
+
+ elf_end(e);
+ return 0;
+}
+
+int
+find_rd_root_image(uint64_t *rd_root_size_off, uint64_t *rd_root_image_off,
+ off_t *pmmap_off, size_t *pmmap_size)
+{
+ GElf_Phdr phdr;
+ size_t i, phdrnum;
+ unsigned long kernel_start, kernel_size;
+ uint64_t adiff, rd_root_size, rd_root_image, size_off, image_off;
+ int error = 1;
+
+ if (symbol_get_u64("rd_root_size", &rd_root_size) != 0)
+ errx(1, "no rd_root_image symbols?");
+
+ if (symbol_get_u64("rd_root_image", &rd_root_image) != 0)
+ errx(1, "no rd_root_image symbols?");
+
+ /* Retrieve number of program headers. */
+ if (elf_getphdrnum(e, &phdrnum) != 0)
+ errx(1, "elf_getphdrnum: %s", elf_errmsg(-1));
+
+ /* Locate the data segment. */
+ for (i = 0; i < phdrnum; i++) {
+ if (gelf_getphdr(e, i, &phdr) != &phdr)
+ errx(1, "gelf_getphdr: %s", elf_errmsg(-1));
+
+ if (phdr.p_type != PT_LOAD)
+ continue;
+
+ kernel_start = phdr.p_paddr;
+ kernel_size = phdr.p_filesz;
+ adiff = phdr.p_vaddr - phdr.p_paddr;
+
+ size_off = rd_root_size - kernel_start;
+ image_off = rd_root_image - kernel_start;
+ if (size_off < adiff || image_off < adiff)
+ continue;
+
+ size_off -= adiff;
+ image_off -= adiff;
+ if (image_off >= kernel_size)
+ continue;
+ if (size_off >= kernel_size)
+ errx(1, "rd_root_size not in data segment");
+
+ *pmmap_off = phdr.p_offset;
+ *pmmap_size = kernel_size;
+ *rd_root_size_off = size_off;
+ *rd_root_image_off = image_off;
+ error = 0;
+ break;
+ }
+
+ return error;
+}
+
+int
+symbol_get_u64(const char *symbol, uint64_t *result)
+{
+ GElf_Sym sym;
+ Elf_Data *data;
+ const char *name;
+ size_t i;
+ int error = 1;
+
+ data = NULL;
+ while ((data = elf_rawdata(symtab, data)) != NULL) {
+ for (i = 0; i < nsymb; i++) {
+ if (gelf_getsym(data, i, &sym) != &sym)
+ continue;
+
+ if (sym.st_name >= strtabsz)
+ break;
+
+ if ((name = elf_strptr(e, strtabndx,
+ sym.st_name)) == NULL)
+ continue;
+
+ if (strcmp(name, symbol) == 0) {
+ if (result)
+ *result = sym.st_value;
+ error = 0;
+ break;
+ }
+ }
+ }
+
+ return error;
}
__dead void
diff --git a/usr.sbin/rdsetroot/rdsetroot.h b/usr.sbin/rdsetroot/rdsetroot.h
deleted file mode 100644
index 6c05227aa75..00000000000
--- a/usr.sbin/rdsetroot/rdsetroot.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/* $OpenBSD: rdsetroot.h,v 1.1 2019/04/05 21:07:11 deraadt Exp $ */
-
-struct elf_fn {
- void (*locate_image)(int, struct elfhdr *, char *, long *, long *,
- off_t *, size_t *);
- int (*find_rd_root_image)(char *, int, Elf_Phdr *, int, long *, long *,
- off_t *, size_t *);
-
-};
-
-extern int debug;
-extern struct elf_fn ELF32_fn;
-extern struct elf_fn ELF64_fn;