Source-Changes-HG archive

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

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



details:   https://anonhg.NetBSD.org/src/rev/0ca8a596f945
branches:  netbsd-6
changeset: 777185:0ca8a596f945
user:      snj <snj%NetBSD.org@localhost>
date:      Fri Jul 14 06:18:25 2017 +0000

description:
Pull up following revision(s) (requested by uwe in ticket #1438):
        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 |  190 ++++++++++++++++++++++++++++++++-------------------
 1 files changed, 117 insertions(+), 73 deletions(-)

diffs (247 lines):

diff -r 881194abf866 -r 0ca8a596f945 sys/kern/exec_elf.c
--- a/sys/kern/exec_elf.c       Fri Jul 14 06:13:07 2017 +0000
+++ b/sys/kern/exec_elf.c       Fri Jul 14 06:18:25 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: exec_elf.c,v 1.37.2.2 2014/02/14 23:21:20 bouyer Exp $ */
+/*     $NetBSD: exec_elf.c,v 1.37.2.3 2017/07/14 06:18:25 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.37.2.2 2014/02/14 23:21:20 bouyer Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.37.2.3 2017/07/14 06:18:25 snj Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_pax.h"
@@ -94,6 +94,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)
@@ -104,6 +105,8 @@
            const Elf_Phdr *, Elf_Addr *, u_long *, int *, 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 *);
 
@@ -860,99 +863,140 @@
     Elf_Ehdr *eh)
 {
        size_t i;
-       Elf_Shdr *sh;
-       Elf_Nhdr *np;
-       size_t shsize;
+       Elf_Phdr *ph;
+       size_t phsize;
+       char *nbuf;
        int error;
        int isnetbsd = 0;
-       char *ndata;
 
        epp->ep_pax_flags = 0;
-       if (eh->e_shnum > MAXSHNUM || eh->e_shnum == 0)
+
+       if (eh->e_phnum > MAXPHNUM || eh->e_phnum == 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);
+       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;
 
-       np = kmem_alloc(MAXNOTESIZE, KM_SLEEP);
-       for (i = 0; i < eh->e_shnum; i++) {
-               Elf_Shdr *shp = &sh[i];
+       nbuf = kmem_alloc(MAXNOTESIZE, KM_SLEEP);
+       for (i = 0; i < eh->e_phnum; i++) {
+               const char *nptr;
+               size_t nlen;
 
-               if (shp->sh_type != SHT_NOTE ||
-                   shp->sh_size > MAXNOTESIZE ||
-                   shp->sh_size < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
+               if (ph[i].p_type != PT_NOTE ||
+                   ph[i].p_filesz > MAXNOTESIZE)
                        continue;
 
-               error = exec_read_from(l, epp->ep_vp, shp->sh_offset, np,
-                   shp->sh_size);
+               nlen = ph[i].p_filesz;
+               error = exec_read_from(l, epp->ep_vp, ph[i].p_offset,
+                                      nbuf, nlen);
                if (error)
                        continue;
 
-               ndata = (char *)(np + 1);
-               switch (np->n_type) {
-               case ELF_NOTE_TYPE_NETBSD_TAG:
-                       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))
-                               goto bad;
-                       isnetbsd = 1;
-                       break;
+               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, MAXNOTESIZE);
 
-               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)) {
+       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;
+
+       switch (np->n_type) {
+       case ELF_NOTE_TYPE_NETBSD_TAG:
+               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))
+                       goto bad;
+               isnetbsd = 1;
+               break;
+
+       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)) {
 bad:
-                           /*
-                            * Ignore GNU tags
-                            */
-                           if (np->n_namesz == ELF_NOTE_GNU_NAMESZ &&
-                               memcmp(ndata, ELF_NOTE_GNU_NAME,
-                               ELF_NOTE_GNU_NAMESZ) == 0)
-                                       break;
+                   /*
+                    * Ignore GNU tags
+                    */
+                   if (np->n_namesz == ELF_NOTE_GNU_NAMESZ &&
+                       memcmp(ndata, ELF_NOTE_GNU_NAME,
+                       ELF_NOTE_GNU_NAMESZ) == 0)
+                               break;
 #ifdef DIAGNOSTIC
-                               printf("%s: bad tag %d: "
-                                   "[%d %d, %d %d, %*.*s %*.*s]\n",
-                                   epp->ep_kname,
-                                   np->n_type,
-                                   np->n_namesz, ELF_NOTE_PAX_NAMESZ,
-                                   np->n_descsz, ELF_NOTE_PAX_DESCSZ,
-                                   ELF_NOTE_PAX_NAMESZ,
-                                   ELF_NOTE_PAX_NAMESZ,
-                                   ndata,
-                                   ELF_NOTE_PAX_NAMESZ,
-                                   ELF_NOTE_PAX_NAMESZ,
-                                   ELF_NOTE_PAX_NAME);
-#endif
-                               continue;
-                       }
-                       (void)memcpy(&epp->ep_pax_flags,
-                           ndata + ELF_NOTE_PAX_NAMESZ,
-                           sizeof(epp->ep_pax_flags));
-                       break;
-
-               case ELF_NOTE_TYPE_SUSE_TAG:
-                       break;
-
-               default:
-#ifdef DIAGNOSTIC
-                       printf("%s: unknown note type %d\n", epp->ep_kname,
-                           np->n_type);
+                       printf("%s: bad tag %d: "
+                           "[%d %d, %d %d, %*.*s %*.*s]\n",
+                           epp->ep_kname,
+                           np->n_type,
+                           np->n_namesz, ELF_NOTE_PAX_NAMESZ,
+                           np->n_descsz, ELF_NOTE_PAX_DESCSZ,
+                           ELF_NOTE_PAX_NAMESZ,
+                           ELF_NOTE_PAX_NAMESZ,
+                           ndata,
+                           ELF_NOTE_PAX_NAMESZ,
+                           ELF_NOTE_PAX_NAMESZ,
+                           ELF_NOTE_PAX_NAME);
 #endif
                        break;
                }
-       }
-       kmem_free(np, MAXNOTESIZE);
+               (void)memcpy(&epp->ep_pax_flags,
+                   ndata + ELF_NOTE_PAX_NAMESZ,
+                   sizeof(epp->ep_pax_flags));
+               break;
+
+       case ELF_NOTE_TYPE_SUSE_TAG:
+               break;
 
-       error = isnetbsd ? 0 : ENOEXEC;
-out:
-       kmem_free(sh, shsize);
-       return error;
+       default:
+#ifdef DIAGNOSTIC
+               printf("%s: unknown note type %d\n", epp->ep_kname,
+                   np->n_type);
+#endif
+               break;
+       }
+
+       return isnetbsd;
 }
 
 int



Home | Main Index | Thread Index | Old Index