Tighten up the ELF signature checks, and actually look for the ABI tag added
in newer glibc versions.
This commit is contained in:
parent
8ec0002acd
commit
b29180b2ff
|
@ -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;
|
||||
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) {
|
||||
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;
|
||||
}
|
||||
else
|
||||
error = ENOEXEC;
|
||||
free(np, M_TEMP);
|
||||
goto out;
|
||||
|
||||
goto out2;
|
||||
next:
|
||||
free(np, M_TEMP);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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 @@ 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;
|
||||
|
|
|
@ -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;
|
||||
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++) {
|
||||
Elf_Phdr *ephp = &ph[i];
|
||||
Elf_Nhdr *np;
|
||||
|
||||
if (ephp->p_type != PT_NOTE ||
|
||||
ephp->p_filesz > 1024 ||
|
||||
ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
|
||||
continue;
|
||||
|
||||
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;
|
||||
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_OSVERSION) {
|
||||
free(np, M_TEMP);
|
||||
np = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check the name and description sizes. */
|
||||
if (np->n_namesz != ELF_NOTE_NETBSD_NAMESZ ||
|
||||
np->n_descsz != ELF_NOTE_NETBSD_DESCSZ)
|
||||
goto out3;
|
||||
|
||||
/* 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
|
||||
|
|
|
@ -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)))
|
||||
|
|
Loading…
Reference in New Issue