diff options
| author | mycroft <mycroft@NetBSD.org> | 2000-12-15 06:14:21 +0000 |
|---|---|---|
| committer | mycroft <mycroft@NetBSD.org> | 2000-12-15 06:14:21 +0000 |
| commit | b29180b2ffee5bef91ef5b8e400c91f31d8fb6d4 (patch) | |
| tree | effebef51cfe432891abafe7dfb667a5d4595315 /sys | |
| parent | 8ec0002acd8f8bd432a1502c464eb6a95f8f0252 (diff) | |
Tighten up the ELF signature checks, and actually look for the ABI tag added
in newer glibc versions.
Diffstat (limited to 'sys')
| -rw-r--r-- | sys/compat/linux/common/linux_exec_elf32.c | 154 | ||||
| -rw-r--r-- | sys/kern/exec_elf32.c | 82 | ||||
| -rw-r--r-- | sys/sys/exec_elf.h | 29 |
3 files changed, 119 insertions, 146 deletions
diff --git a/sys/compat/linux/common/linux_exec_elf32.c b/sys/compat/linux/common/linux_exec_elf32.c index ef25851d68d..9046f049731 100644 --- a/sys/compat/linux/common/linux_exec_elf32.c +++ b/sys/compat/linux/common/linux_exec_elf32.c @@ -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 @@ ELFNAME2(linux,gcc_signature)(p, epp, eh) 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 @@ ELFNAME2(linux,gcc_signature)(p, epp, eh) 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 @@ ELFNAME2(linux,gcc_signature)(p, epp, eh) #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; - - /* 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) { + 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; + + 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; + + /* 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; - goto out3; - } - - goto out2; - - /* 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; - - /* Is the name "GNU\0"? */ - if (memcmp((notep + sizeof(Elf_Nhdr)), - ELF_NOTE_GNU_NAME, ELF_NOTE_GNU_NAMESZ)) - goto out2; - - /* 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; + else + error = ENOEXEC; + free(np, M_TEMP); + goto out; - /* All checks succeeded. */ - error = 0; - goto out3; + next: + free(np, M_TEMP); + continue; } - error = ENOEXEC; - -out1: - free(ph, M_TEMP); -#ifdef DEBUG_LINUX - printf("linux_signature: out1=%d\n", error); -#endif - return error; + /* 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; + } -out2: error = ENOEXEC; -out3: - free(notep, M_TEMP); +out: 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 @@ ELFNAME2(linux,probe)(p, epp, eh, itp, pos) 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 --git a/sys/kern/exec_elf32.c b/sys/kern/exec_elf32.c index de142e4ec8b..563346fba8b 100644 --- a/sys/kern/exec_elf32.c +++ b/sys/kern/exec_elf32.c @@ -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 @@ ELFNAME(check_header)(Elf_Ehdr *eh, int type) 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 @@ int 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; - - 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) - continue; + 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; - np = (Elf_Nhdr *)malloc(ph->p_filesz, M_TEMP, M_WAITOK); - if ((error = ELFNAME(read_from)(p, epp->ep_vp, ph->p_offset, - (caddr_t)np, ph->p_filesz)) != 0) - goto out2; + for (i = 0; i < eh->e_phnum; i++) { + Elf_Phdr *ephp = &ph[i]; + Elf_Nhdr *np; - if (np->n_type != ELF_NOTE_TYPE_OSVERSION) { - free(np, M_TEMP); - np = NULL; + if (ephp->p_type != PT_NOTE || + ephp->p_filesz > 1024 || + ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ) continue; - } - /* Check the name and description sizes. */ - if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ || - np->n_descsz != ELF_NOTE_NETBSD_DESCSZ) - 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; - /* Is the name "NetBSD\0\0"? */ - if (memcmp((np + 1), ELF_NOTE_NETBSD_NAME, + if (np->n_type != ELF_NOTE_TYPE_NETBSD_TAG || + np->n_namesz != ELF_NOTE_NETBSD_NAMESZ || + np->n_descsz != ELF_NOTE_NETBSD_DESCSZ || + memcmp((caddr_t)(np + 1), ELF_NOTE_NETBSD_NAME, ELF_NOTE_NETBSD_NAMESZ)) - goto out3; + goto next; - /* XXX: We could check for the specific emulation here */ - /* All checks succeeded. */ error = 0; - goto out2; + free(np, M_TEMP); + goto out; + + next: + free(np, M_TEMP); + continue; } -out3: error = ENOEXEC; -out2: - if (np) - free(np, M_TEMP); -out1: - free(hph, M_TEMP); - return error; +out: + free(ph, M_TEMP); + return (error); } int diff --git a/sys/sys/exec_elf.h b/sys/sys/exec_elf.h index b1396c084f4..270edbe3c80 100644 --- a/sys/sys/exec_elf.h +++ b/sys/sys/exec_elf.h @@ -1,4 +1,4 @@ -/* $NetBSD: exec_elf.h,v 1.39 2000/07/26 02:04:53 mycroft Exp $ */ +/* $NetBSD: exec_elf.h,v 1.40 2000/12/15 06:14:21 mycroft Exp $ */ /*- * Copyright (c) 1994 The NetBSD Foundation, Inc. @@ -557,13 +557,21 @@ typedef struct { Elf64_Half n_type; } Elf64_Nhdr; -#define ELF_NOTE_TYPE_OSVERSION 1 +#define ELF_NOTE_TYPE_ABI_TAG 1 -/* NetBSD-specific note type: OS Version. desc is 4-byte NetBSD integer. */ -#define ELF_NOTE_NETBSD_TYPE_OSVERSION ELF_NOTE_TYPE_OSVERSION +/* GNU-specific note name and description sizes */ +#define ELF_NOTE_ABI_NAMESZ 4 +#define ELF_NOTE_ABI_DESCSZ 16 +/* GNU-specific note name */ +#define ELF_NOTE_ABI_NAME "GNU\0" + +/* GNU-specific OS/version value stuff */ +#define ELF_NOTE_ABI_OS_LINUX 0 +#define ELF_NOTE_ABI_OS_HURD 1 +#define ELF_NOTE_ABI_OS_SOLARIS 2 /* NetBSD-specific note type: Emulation name. desc is emul name string. */ -#define ELF_NOTE_NETBSD_TYPE_EMULNAME 2 +#define ELF_NOTE_TYPE_NETBSD_TAG 1 /* NetBSD-specific note name and description sizes */ #define ELF_NOTE_NETBSD_NAMESZ 7 @@ -571,17 +579,6 @@ typedef struct { /* NetBSD-specific note name */ #define ELF_NOTE_NETBSD_NAME "NetBSD\0\0" -/* GNU-specific note name and description sizes */ -#define ELF_NOTE_GNU_NAMESZ 4 -#define ELF_NOTE_GNU_DESCSZ 4 -/* GNU-specific note name */ -#define ELF_NOTE_GNU_NAME "GNU\0" - -/* GNU-specific OS/version value stuff */ -#define ELF_NOTE_GNU_OSMASK (__uint32_t)0xff000000 -#define ELF_NOTE_GNU_OSLINUX (__uint32_t)0x01000000 -#define ELF_NOTE_GNU_OSMACH (__uint32_t)0x00000000 - #if defined(ELFSIZE) #define CONCAT(x,y) __CONCAT(x,y) #define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x))) |
