Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-7]: src/sys/kern Pull up following revision(s) (requested by uwe ...



details:   https://anonhg.NetBSD.org/src/rev/9564ceffc431
branches:  netbsd-7
changeset: 800163:9564ceffc431
user:      snj <snj%NetBSD.org@localhost>
date:      Sat Mar 18 05:22:18 2017 +0000

description:
Pull up following revision(s) (requested by uwe in ticket #1368):
        sys/kern/exec_elf.c: revision 1.88 via patch
netbsd_elf_signature - look at note segments (phdrs) not note
sections.  They point to the same data in the file, but sections are
for linkers and are not necessarily present in an executable.
The original switch from phdrs to shdrs seems to be just a cop-out to
avoid parsing multiple notes per segment, which doesn't really avoid
the problem b/c sections also can contain multiple notes.

diffstat:

 sys/kern/exec_elf.c |  331 +++++++++++++++++++++++++++------------------------
 1 files changed, 174 insertions(+), 157 deletions(-)

diffs (truncated from 391 to 300 lines):

diff -r cda0c7b00ce3 -r 9564ceffc431 sys/kern/exec_elf.c
--- a/sys/kern/exec_elf.c       Sat Mar 18 05:13:22 2017 +0000
+++ b/sys/kern/exec_elf.c       Sat Mar 18 05:22:18 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: exec_elf.c,v 1.69.2.4 2016/01/26 01:18:37 riz Exp $    */
+/*     $NetBSD: exec_elf.c,v 1.69.2.5 2017/03/18 05:22:18 snj Exp $    */
 
 /*-
  * Copyright (c) 1994, 2000, 2005 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.69.2.4 2016/01/26 01:18:37 riz Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.69.2.5 2017/03/18 05:22:18 snj Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_pax.h"
@@ -95,6 +95,7 @@
 #define elf_load_psection      ELFNAME(load_psection)
 #define exec_elf_makecmds      ELFNAME2(exec,makecmds)
 #define netbsd_elf_signature   ELFNAME2(netbsd,signature)
+#define netbsd_elf_note        ELFNAME2(netbsd,note)
 #define netbsd_elf_probe       ELFNAME2(netbsd,probe)
 #define        coredump                ELFNAMEEND(coredump)
 #define        elf_free_emul_arg       ELFNAME(free_emul_arg)
@@ -107,6 +108,8 @@
     Elf_Addr *, u_long *, int);
 
 int    netbsd_elf_signature(struct lwp *, struct exec_package *, Elf_Ehdr *);
+int    netbsd_elf_note(struct exec_package *, const Elf_Nhdr *, const char *,
+           const char *);
 int    netbsd_elf_probe(struct lwp *, struct exec_package *, void *, char *,
            vaddr_t *);
 
@@ -885,13 +888,84 @@
     Elf_Ehdr *eh)
 {
        size_t i;
-       Elf_Shdr *sh;
-       Elf_Nhdr *np;
-       size_t shsize, nsize;
+       Elf_Phdr *ph;
+       size_t phsize;
+       char *nbuf;
        int error;
        int isnetbsd = 0;
-       char *ndata, *ndesc;
-       
+
+       epp->ep_pax_flags = 0;
+
+       if (eh->e_phnum > ELF_MAXPHNUM || eh->e_phnum == 0)
+               return ENOEXEC;
+
+       phsize = eh->e_phnum * sizeof(Elf_Phdr);
+       ph = kmem_alloc(phsize, KM_SLEEP);
+       error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize);
+       if (error)
+               goto out;
+
+       nbuf = kmem_alloc(ELF_MAXNOTESIZE, KM_SLEEP);
+       for (i = 0; i < eh->e_phnum; i++) {
+               const char *nptr;
+               size_t nlen;
+
+               if (ph[i].p_type != PT_NOTE ||
+                   ph[i].p_filesz > ELF_MAXNOTESIZE)
+                       continue;
+
+               nlen = ph[i].p_filesz;
+               error = exec_read_from(l, epp->ep_vp, ph[i].p_offset,
+                                      nbuf, nlen);
+               if (error)
+                       continue;
+
+               nptr = nbuf;
+               while (nlen > 0) {
+                       const Elf_Nhdr *np;
+                       const char *ndata, *ndesc;
+
+                       /* note header */
+                       np = (const Elf_Nhdr *)nptr;
+                       if (nlen < sizeof(*np)) {
+                               break;
+                       }
+                       nptr += sizeof(*np);
+                       nlen -= sizeof(*np);
+
+                       /* note name */
+                       ndata = nptr;
+                       if (nlen < roundup(np->n_namesz, 4)) {
+                               break;
+                       }
+                       nptr += roundup(np->n_namesz, 4);
+                       nlen -= roundup(np->n_namesz, 4);
+
+                       /* note description */
+                       ndesc = nptr;
+                       if (nlen < roundup(np->n_descsz, 4)) {
+                               break;
+                       }
+                       nptr += roundup(np->n_descsz, 4);
+                       nlen -= roundup(np->n_descsz, 4);
+
+                       isnetbsd |= netbsd_elf_note(epp, np, ndata, ndesc);
+               }
+       }
+       kmem_free(nbuf, ELF_MAXNOTESIZE);
+
+       error = isnetbsd ? 0 : ENOEXEC;
+out:
+       kmem_free(ph, phsize);
+       return error;
+}
+
+int
+netbsd_elf_note(struct exec_package *epp,
+               const Elf_Nhdr *np, const char *ndata, const char *ndesc)
+{
+       int isnetbsd = 0;
+
 #ifdef DIAGNOSTIC
        const char *badnote;
 #define BADNOTE(n) badnote = (n)
@@ -899,172 +973,115 @@
 #define BADNOTE(n)
 #endif
 
-       epp->ep_pax_flags = 0;
-       if (eh->e_shnum > ELF_MAXSHNUM || eh->e_shnum == 0)
-               return ENOEXEC;
-
-       shsize = eh->e_shnum * sizeof(Elf_Shdr);
-       sh = kmem_alloc(shsize, KM_SLEEP);
-       error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
-       if (error)
-               goto out;
-
-       np = kmem_alloc(ELF_MAXNOTESIZE, KM_SLEEP);
-       for (i = 0; i < eh->e_shnum; i++) {
-               Elf_Shdr *shp = &sh[i];
-
-               if (shp->sh_type != SHT_NOTE ||
-                   shp->sh_size > ELF_MAXNOTESIZE ||
-                   shp->sh_size < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
-                       continue;
-
-               error = exec_read_from(l, epp->ep_vp, shp->sh_offset, np,
-                   shp->sh_size);
-               if (error)
-                       continue;
-
-               /* Point to the note, skip the header */
-               ndata = (char *)(np + 1);
+       switch (np->n_type) {
+       case ELF_NOTE_TYPE_NETBSD_TAG:
+               /* It is us */
+               if (np->n_namesz == ELF_NOTE_NETBSD_NAMESZ &&
+                   np->n_descsz == ELF_NOTE_NETBSD_DESCSZ &&
+                   memcmp(ndata, ELF_NOTE_NETBSD_NAME,
+                   ELF_NOTE_NETBSD_NAMESZ) == 0) {
+                       memcpy(&epp->ep_osversion, ndesc,
+                           ELF_NOTE_NETBSD_DESCSZ);
+                       isnetbsd = 1;
+                       break;
+               }
 
                /*
-                * Padding is present if necessary to ensure 4-byte alignment.
-                * The actual section size is therefore:
-                *    header size + 4-byte aligned name + 4-byte aligned desc
-                * Ensure this size is consistent with what is indicated
-                * in sh_size. The first check avoids integer overflows.
-                *
-                * Binaries from before NetBSD 1.6 have two notes in the same
-                * note section.  The second note was never used, so as long as
-                * the section is at least as big as it should be, it's ok.
-                * These binaries also have a second note section with a note of
-                * type ELF_NOTE_TYPE_NETBSD_TAG, which can be ignored as well.
+                * Ignore SuSE tags; SuSE's n_type is the same the
+                * NetBSD one.
                 */
-               if (np->n_namesz > shp->sh_size || np->n_descsz > shp->sh_size) {
-                       BADNOTE("note size limit");
-                       goto bad;
-               }
-               nsize = sizeof(*np) + roundup(np->n_namesz, 4) +
-                   roundup(np->n_descsz, 4);
-               if (nsize > shp->sh_size) {
-                       BADNOTE("note size");
-                       goto bad;
-               }
-               ndesc = ndata + roundup(np->n_namesz, 4);
+               if (np->n_namesz == ELF_NOTE_SUSE_NAMESZ &&
+                   memcmp(ndata, ELF_NOTE_SUSE_NAME,
+                   ELF_NOTE_SUSE_NAMESZ) == 0)
+                       break;
+               /*
+                * Ignore old GCC
+                */
+               if (np->n_namesz == ELF_NOTE_OGCC_NAMESZ &&
+                   memcmp(ndata, ELF_NOTE_OGCC_NAME,
+                   ELF_NOTE_OGCC_NAMESZ) == 0)
+                       break;
+               BADNOTE("NetBSD tag");
+               goto bad;
 
-               switch (np->n_type) {
-               case ELF_NOTE_TYPE_NETBSD_TAG:
-                       /* It is us */
-                       if (np->n_namesz == ELF_NOTE_NETBSD_NAMESZ &&
-                           np->n_descsz == ELF_NOTE_NETBSD_DESCSZ &&
-                           memcmp(ndata, ELF_NOTE_NETBSD_NAME,
-                           ELF_NOTE_NETBSD_NAMESZ) == 0) {
-                               memcpy(&epp->ep_osversion, ndesc,
-                                   ELF_NOTE_NETBSD_DESCSZ);
-                               isnetbsd = 1;
-                               break;
-                       }
-
-                       /*
-                        * Ignore SuSE tags; SuSE's n_type is the same the
-                        * NetBSD one.
-                        */
-                       if (np->n_namesz == ELF_NOTE_SUSE_NAMESZ &&
-                           memcmp(ndata, ELF_NOTE_SUSE_NAME,
-                           ELF_NOTE_SUSE_NAMESZ) == 0)
-                               break;
-                       /*
-                        * Ignore old GCC
-                        */
-                       if (np->n_namesz == ELF_NOTE_OGCC_NAMESZ &&
-                           memcmp(ndata, ELF_NOTE_OGCC_NAME,
-                           ELF_NOTE_OGCC_NAMESZ) == 0)
-                               break;
-                       BADNOTE("NetBSD tag");
-                       goto bad;
+       case ELF_NOTE_TYPE_PAX_TAG:
+               if (np->n_namesz == ELF_NOTE_PAX_NAMESZ &&
+                   np->n_descsz == ELF_NOTE_PAX_DESCSZ &&
+                   memcmp(ndata, ELF_NOTE_PAX_NAME,
+                   ELF_NOTE_PAX_NAMESZ) == 0) {
+                       memcpy(&epp->ep_pax_flags, ndesc,
+                           sizeof(epp->ep_pax_flags));
+                       break;
+               }
+               BADNOTE("PaX tag");
+               goto bad;
 
-               case ELF_NOTE_TYPE_PAX_TAG:
-                       if (np->n_namesz == ELF_NOTE_PAX_NAMESZ &&
-                           np->n_descsz == ELF_NOTE_PAX_DESCSZ &&
-                           memcmp(ndata, ELF_NOTE_PAX_NAME,
-                           ELF_NOTE_PAX_NAMESZ) == 0) {
-                               memcpy(&epp->ep_pax_flags, ndesc,
-                                   sizeof(epp->ep_pax_flags));
-                               break;
+       case ELF_NOTE_TYPE_MARCH_TAG:
+               /* Copy the machine arch into the package. */
+               if (np->n_namesz == ELF_NOTE_MARCH_NAMESZ
+                   && memcmp(ndata, ELF_NOTE_MARCH_NAME,
+                           ELF_NOTE_MARCH_NAMESZ) == 0) {
+                       /* Do not truncate the buffer */
+                       if (np->n_descsz > sizeof(epp->ep_machine_arch)) {
+                               BADNOTE("description size limit");
+                               goto bad;
                        }
-                       BADNOTE("PaX tag");
-                       goto bad;
+                       /*
+                        * Ensure ndesc is NUL-terminated and of the
+                        * expected length.
+                        */
+                       if (strnlen(ndesc, np->n_descsz) + 1 !=
+                           np->n_descsz) {
+                               BADNOTE("description size");
+                               goto bad;
+                       }
+                       strlcpy(epp->ep_machine_arch, ndesc,
+                           sizeof(epp->ep_machine_arch));
+                       break;
+               }
+               BADNOTE("march tag");
+               goto bad;
 
-               case ELF_NOTE_TYPE_MARCH_TAG:
-                       /* Copy the machine arch into the package. */
-                       if (np->n_namesz == ELF_NOTE_MARCH_NAMESZ
-                           && memcmp(ndata, ELF_NOTE_MARCH_NAME,
-                                   ELF_NOTE_MARCH_NAMESZ) == 0) {
-                               /* Do not truncate the buffer */
-                               if (np->n_descsz > sizeof(epp->ep_machine_arch)) {
-                                       BADNOTE("description size limit");
-                                       goto bad;
-                               }
-                               /*
-                                * Ensure ndesc is NUL-terminated and of the
-                                * expected length.
-                                */



Home | Main Index | Thread Index | Old Index