Source-Changes-HG archive

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

[src/trunk]: src/sys Tighten up the ELF signature checks, and actually look f...



details:   https://anonhg.NetBSD.org/src/rev/73aa57b588be
branches:  trunk
changeset: 500665:73aa57b588be
user:      mycroft <mycroft%NetBSD.org@localhost>
date:      Fri Dec 15 06:14:21 2000 +0000

description:
Tighten up the ELF signature checks, and actually look for the ABI tag added
in newer glibc versions.

diffstat:

 sys/compat/linux/common/linux_exec_elf32.c |  152 ++++++++++++----------------
 sys/kern/exec_elf32.c                      |   86 ++++++++--------
 sys/sys/exec_elf.h                         |   29 ++---
 3 files changed, 120 insertions(+), 147 deletions(-)

diffs (truncated from 419 to 300 lines):

diff -r c552f82c72a8 -r 73aa57b588be sys/compat/linux/common/linux_exec_elf32.c
--- a/sys/compat/linux/common/linux_exec_elf32.c        Fri Dec 15 02:22:50 2000 +0000
+++ b/sys/compat/linux/common/linux_exec_elf32.c        Fri Dec 15 06:14:21 2000 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: linux_exec_elf32.c,v 1.49 2000/12/01 12:28:33 jdolecek Exp $   */
+/*     $NetBSD: linux_exec_elf32.c,v 1.50 2000/12/15 06:14:21 mycroft Exp $    */
 
 /*-
- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
+ * Copyright (c) 1995, 1998, 2000 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -71,7 +71,7 @@
 #include <compat/linux/linux_syscall.h>
 
 static int ELFNAME2(linux,signature) __P((struct proc *, struct exec_package *,
-       Elf_Ehdr *));
+       Elf_Ehdr *, char *));
 #ifdef LINUX_GCC_SIGNATURE
 static int ELFNAME2(linux,gcc_signature) __P((struct proc *p,
        struct exec_package *, Elf_Ehdr *));
@@ -95,18 +95,18 @@
        struct exec_package *epp;
        Elf_Ehdr *eh;
 {
-       size_t shsize = sizeof(Elf_Shdr) * eh->e_shnum;
+       size_t shsize;
        size_t i;
        static const char signature[] = "\0GCC: (GNU) ";
        char buf[sizeof(signature) - 1];
        Elf_Shdr *sh;
        int error;
 
-       error = ENOEXEC;
+       shsize = eh->e_shnum * sizeof(Elf_Shdr);
        sh = (Elf_Shdr *) malloc(shsize, M_TEMP, M_WAITOK);
-
-       if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_shoff,
-           (caddr_t) sh, shsize)) != 0)
+       error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_shoff, (caddr_t)sh,
+           shsize);
+       if (error)
                goto out;
 
        for (i = 0; i < eh->e_shnum; i++) {
@@ -123,9 +123,10 @@
                    s->sh_size < sizeof(signature) - 1)
                        continue;
 
-               if ((error = ELFNAME(read_from)(p, epp->ep_vp, s->sh_offset,
-                   (caddr_t) buf, sizeof(signature) - 1)) != 0)
-                       goto out;
+               error = ELFNAME(read_from)(p, epp->ep_vp, s->sh_offset,
+                   (caddr_t)buf, sizeof(signature) - 1);
+               if (error)
+                       continue;
 
                /*
                 * error is 0, if the signatures match we are done.
@@ -133,115 +134,90 @@
 #ifdef DEBUG_LINUX
                printf("linux_gcc_sig: sig=%s\n", buf);
 #endif
-               if (memcmp(buf, signature, sizeof(signature) - 1) == 0)
+               if (!memcmp(buf, signature, sizeof(signature) - 1)) {
+                       error = 0;
                        goto out;
+               }
        }
+       error = ENOEXEC;
 
 out:
        free(sh, M_TEMP);
-#ifdef DEBUG_LINUX
-       printf("linux_gcc_sig: returning %d\n", error);
-#endif
-       return error;
+       return (error);
 }
 #endif
 
 static int
-ELFNAME2(linux,signature)(p, epp, eh)
+ELFNAME2(linux,signature)(p, epp, eh, itp)
        struct proc *p;
        struct exec_package *epp;
        Elf_Ehdr *eh;
+       char *itp;
 {
        size_t i;
        Elf_Phdr *ph;
-       Elf_Nhdr *notep;
        size_t phsize;
-       int error = ENOEXEC;
+       int error;
 
        phsize = eh->e_phnum * sizeof(Elf_Phdr);
        ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
-       if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
-                                       (caddr_t) ph, phsize)) != 0)
-               goto out1;
+       error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph,
+           phsize);
+       if (error)
+               goto out;
 
        for (i = 0; i < eh->e_phnum; i++) {
                Elf_Phdr *ephp = &ph[i];
-               u_int32_t ostype;
+               Elf_Nhdr *np;
+               u_int32_t *abi;
 
-               if (ephp->p_type != PT_INTERP /* XAX PT_NOTE */
-#if 0
-                   || ephp->p_flags != 0
-                   || ephp->p_filesz < sizeof(Elf_Nhdr))
-#endif
-                   )
+               if (ephp->p_type != PT_NOTE ||
+                   ephp->p_filesz > 1024 ||
+                   ephp->p_filesz < sizeof(Elf_Nhdr) + 20)
                        continue;
 
-               notep = (Elf_Nhdr *)malloc(ephp->p_filesz+1, M_TEMP, M_WAITOK);
-               if ((error = ELFNAME(read_from)(p, epp->ep_vp, ephp->p_offset,
-                                       (caddr_t)notep, ephp->p_filesz)) != 0)
-                       goto out3;
+               np = (Elf_Nhdr *)malloc(ephp->p_filesz, M_TEMP, M_WAITOK);
+               error = ELFNAME(read_from)(p, epp->ep_vp, ephp->p_offset,
+                   (caddr_t)np, ephp->p_filesz);
+               if (error)
+                       goto next;
 
-               /* Check for "linux" in the intepreter name. */
-               if (ephp->p_filesz < 8 + 5) {
-                       error = ENOEXEC;
-                       goto out3;
-               }
-#ifdef DEBUG_LINUX
-               printf("linux_signature: interp=%s\n", (char *)notep);
-#endif
-               if (strncmp(&((char *)notep)[8], "linux", 5) == 0 ||
-                   strncmp((char *)notep, "/lib/ld.so.", 11) == 0) {
-                       error = 0;
-                       goto out3;
-               }
-
-               goto out2;
+               if (np->n_type != ELF_NOTE_TYPE_ABI_TAG ||
+                   np->n_namesz != ELF_NOTE_ABI_NAMESZ ||
+                   np->n_descsz != ELF_NOTE_ABI_DESCSZ ||
+                   memcmp((caddr_t)(np + 1), ELF_NOTE_ABI_NAME,
+                   ELF_NOTE_ABI_NAMESZ))
+                       goto next;
 
-               /* XXX XAX Should handle NETBSD_TYPE_EMULNAME */
-               if (notep->n_type != ELF_NOTE_TYPE_OSVERSION) {
-                       free(notep, M_TEMP);
-                       continue;
-               }
-
-               /* Check the name and description sizes. */
-               if (notep->n_namesz != ELF_NOTE_GNU_NAMESZ ||
-                   notep->n_descsz != ELF_NOTE_GNU_DESCSZ)
-                       goto out2;
+               /* Make sure the OS is Linux. */
+               abi = (u_int32_t *)((caddr_t)np + sizeof(Elf_Nhdr) +
+                   np->n_namesz);
+               if (abi[0] == ELF_NOTE_ABI_OS_LINUX)
+                       error = 0;
+               else
+                       error = ENOEXEC;
+               free(np, M_TEMP);
+               goto out;
 
-               /* Is the name "GNU\0"? */
-               if (memcmp((notep + sizeof(Elf_Nhdr)),
-                          ELF_NOTE_GNU_NAME, ELF_NOTE_GNU_NAMESZ))
-                       goto out2;
+       next:
+               free(np, M_TEMP);
+               continue;
+       }
 
-               /* Make sure the OS is Linux */
-               ostype = (u_int32_t)(*((u_int32_t *)notep + sizeof(Elf_Nhdr) +
-                   notep->n_namesz)) & ELF_NOTE_GNU_OSMASK;
-               if (ostype != ELF_NOTE_GNU_OSLINUX)
-                       goto out2;
-
-               /* All checks succeeded. */
-               error = 0;
-               goto out3;
+       /* Check for certain intepreter names. */
+       if (itp[0]) {
+               if (!strncmp(itp, "/lib/ld-linux", 13) ||
+                   !strncmp(itp, "/lib/ld.so.", 11))
+                       error = 0;
+               else
+                       error = ENOEXEC;
+               goto out;
        }
 
        error = ENOEXEC;
-
-out1:
+out:
        free(ph, M_TEMP);
-#ifdef DEBUG_LINUX
-       printf("linux_signature: out1=%d\n", error);
-#endif
-       return error;
-
-out2:
-       error = ENOEXEC;
-out3:
-       free(notep, M_TEMP);
-       free(ph, M_TEMP);
-#ifdef DEBUG_LINUX
-       printf("linux_signature: out2,3=%d\n", error);
-#endif
-       return error;
+       return (error);
 }
 
 int
@@ -256,7 +232,7 @@
        int error;
        size_t len;
 
-       if ((error = ELFNAME2(linux,signature)(p, epp, eh)) != 0)
+       if ((error = ELFNAME2(linux,signature)(p, epp, eh, itp)) != 0)
 #ifdef LINUX_GCC_SIGNATURE
                if ((error = ELFNAME2(linux,gcc_signature)(p, epp, eh)) != 0)
                        return error;
diff -r c552f82c72a8 -r 73aa57b588be sys/kern/exec_elf32.c
--- a/sys/kern/exec_elf32.c     Fri Dec 15 02:22:50 2000 +0000
+++ b/sys/kern/exec_elf32.c     Fri Dec 15 06:14:21 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: exec_elf32.c,v 1.60 2000/12/11 05:29:02 mycroft Exp $  */
+/*     $NetBSD: exec_elf32.c,v 1.61 2000/12/15 06:14:21 mycroft Exp $  */
 
 /*-
  * Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
@@ -179,20 +179,24 @@
 
        if (memcmp(eh->e_ident, ELFMAG, SELFMAG) != 0 ||
            eh->e_ident[EI_CLASS] != ELFCLASS)
-               return ENOEXEC;
+               return (ENOEXEC);
 
        switch (eh->e_machine) {
 
        ELFDEFNNAME(MACHDEP_ID_CASES)
 
        default:
-               return ENOEXEC;
+               return (ENOEXEC);
        }
 
        if (eh->e_type != type)
-               return ENOEXEC;
+               return (ENOEXEC);
 
-       return 0;
+       if (eh->e_shnum > 128 ||
+           eh->e_phnum > 128)
+               return (ENOEXEC);
+
+       return (0);
 }
 
 /*
@@ -638,57 +642,53 @@
 ELFNAME2(netbsd,signature)(struct proc *p, struct exec_package *epp,
     Elf_Ehdr *eh)
 {
-       Elf_Phdr *hph, *ph;
-       Elf_Nhdr *np = NULL;
+       size_t i;
+       Elf_Phdr *ph;
        size_t phsize;
        int error;
 
        phsize = eh->e_phnum * sizeof(Elf_Phdr);
-       hph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
-       if ((error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff,
-           (caddr_t)hph, phsize)) != 0)
-               goto out1;
+       ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK);
+       error = ELFNAME(read_from)(p, epp->ep_vp, eh->e_phoff, (caddr_t)ph,
+           phsize);
+       if (error)
+               goto out;
 
-       for (ph = hph;  ph < &hph[eh->e_phnum]; ph++) {
-               if (ph->p_type != PT_NOTE ||
-                   ph->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
+       for (i = 0; i < eh->e_phnum; i++) {



Home | Main Index | Thread Index | Old Index