Don't put aggregate structs 4K large on the kernel stack, especially when
we can recurse when loading dependencies and that the kstack is limited to something like 6 or 7KB. Having a single dependency caused an instant double panic, and I stronly suspect some of the other strange "events" that I have seen are possibly as a result of taking a couple of interrupts with a large chunk of the stack already in use. While here, fix a minor logic hiccup in a sanity check.
This commit is contained in:
parent
21ce23eb91
commit
caab6e909e
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: link_elf.c,v 1.8 1998/10/25 17:44:51 phk Exp $
|
||||
* $Id: link_elf.c,v 1.9 1998/11/04 15:20:57 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -393,10 +393,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct proc* p = curproc; /* XXX */
|
||||
union {
|
||||
Elf_Ehdr hdr;
|
||||
char buf[PAGE_SIZE];
|
||||
} u;
|
||||
Elf_Ehdr *hdr;
|
||||
caddr_t firstpage;
|
||||
int nbytes, i;
|
||||
Elf_Phdr *phdr;
|
||||
Elf_Phdr *phlimit;
|
||||
@ -426,6 +424,7 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
pathname = linker_search_path(filename);
|
||||
if (pathname == NULL)
|
||||
return ENOENT;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
|
||||
error = vn_open(&nd, FREAD, 0);
|
||||
free(pathname, M_LINKER);
|
||||
@ -435,35 +434,41 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
/*
|
||||
* Read the elf header from the file.
|
||||
*/
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &u, sizeof u, 0,
|
||||
firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
|
||||
if (firstpage == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
hdr = (Elf_Ehdr *)firstpage;
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
|
||||
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
|
||||
nbytes = sizeof u - resid;
|
||||
nbytes = PAGE_SIZE - resid;
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (!IS_ELF(u.hdr)) {
|
||||
if (!IS_ELF(*hdr)) {
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
|
||||
|| u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
|
||||
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
|
||||
|| hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
|
||||
link_elf_error("Unsupported file layout");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| u.hdr.e_version != EV_CURRENT) {
|
||||
if (hdr->e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| hdr->e_version != EV_CURRENT) {
|
||||
link_elf_error("Unsupported file version");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) {
|
||||
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
|
||||
link_elf_error("Unsupported file type");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_machine != ELF_TARG_MACH) {
|
||||
if (hdr->e_machine != ELF_TARG_MACH) {
|
||||
link_elf_error("Unsupported machine");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
@ -474,9 +479,9 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
* not strictly required by the ABI specification, but it seems to
|
||||
* always true in practice. And, it simplifies things considerably.
|
||||
*/
|
||||
if (!((u.hdr.e_phentsize == sizeof(Elf_Phdr))
|
||||
|| (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE)
|
||||
|| (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes)))
|
||||
if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
|
||||
(hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
|
||||
(hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
|
||||
link_elf_error("Unreadable program headers");
|
||||
|
||||
/*
|
||||
@ -485,8 +490,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
* We rely on there being exactly two load segments, text and data,
|
||||
* in that order.
|
||||
*/
|
||||
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
|
||||
phlimit = phdr + u.hdr.e_phnum;
|
||||
phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
|
||||
phlimit = phdr + hdr->e_phnum;
|
||||
nsegs = 0;
|
||||
phdyn = NULL;
|
||||
phphdr = NULL;
|
||||
@ -618,8 +623,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
goto out;
|
||||
|
||||
/* Try and load the symbol table if it's present. (you can strip it!) */
|
||||
nbytes = u.hdr.e_shnum * u.hdr.e_shentsize;
|
||||
if (nbytes == 0 || u.hdr.e_shoff == 0)
|
||||
nbytes = hdr->e_shnum * hdr->e_shentsize;
|
||||
if (nbytes == 0 || hdr->e_shoff == 0)
|
||||
goto nosyms;
|
||||
shdr = malloc(nbytes, M_LINKER, M_WAITOK);
|
||||
if (shdr == NULL) {
|
||||
@ -628,13 +633,13 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
}
|
||||
bzero(shdr, nbytes);
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp,
|
||||
(caddr_t)shdr, nbytes, u.hdr.e_shoff,
|
||||
(caddr_t)shdr, nbytes, hdr->e_shoff,
|
||||
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
|
||||
if (error)
|
||||
goto out;
|
||||
symtabindex = -1;
|
||||
symstrindex = -1;
|
||||
for (i = 0; i < u.hdr.e_shnum; i++) {
|
||||
for (i = 0; i < hdr->e_shnum; i++) {
|
||||
if (shdr[i].sh_type == SHT_SYMTAB) {
|
||||
symtabindex = i;
|
||||
symstrindex = shdr[i].sh_link;
|
||||
@ -677,6 +682,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
linker_file_unload(lf);
|
||||
if (shdr)
|
||||
free(shdr, M_LINKER);
|
||||
if (firstpage)
|
||||
free(firstpage, M_LINKER);
|
||||
VOP_UNLOCK(nd.ni_vp, 0, p);
|
||||
vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: link_elf.c,v 1.8 1998/10/25 17:44:51 phk Exp $
|
||||
* $Id: link_elf.c,v 1.9 1998/11/04 15:20:57 peter Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -393,10 +393,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct proc* p = curproc; /* XXX */
|
||||
union {
|
||||
Elf_Ehdr hdr;
|
||||
char buf[PAGE_SIZE];
|
||||
} u;
|
||||
Elf_Ehdr *hdr;
|
||||
caddr_t firstpage;
|
||||
int nbytes, i;
|
||||
Elf_Phdr *phdr;
|
||||
Elf_Phdr *phlimit;
|
||||
@ -426,6 +424,7 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
pathname = linker_search_path(filename);
|
||||
if (pathname == NULL)
|
||||
return ENOENT;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, pathname, p);
|
||||
error = vn_open(&nd, FREAD, 0);
|
||||
free(pathname, M_LINKER);
|
||||
@ -435,35 +434,41 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
/*
|
||||
* Read the elf header from the file.
|
||||
*/
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp, (void*) &u, sizeof u, 0,
|
||||
firstpage = malloc(PAGE_SIZE, M_LINKER, M_WAITOK);
|
||||
if (firstpage == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
hdr = (Elf_Ehdr *)firstpage;
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp, firstpage, PAGE_SIZE, 0,
|
||||
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
|
||||
nbytes = sizeof u - resid;
|
||||
nbytes = PAGE_SIZE - resid;
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
if (!IS_ELF(u.hdr)) {
|
||||
if (!IS_ELF(*hdr)) {
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS
|
||||
|| u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) {
|
||||
if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS
|
||||
|| hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
|
||||
link_elf_error("Unsupported file layout");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| u.hdr.e_version != EV_CURRENT) {
|
||||
if (hdr->e_ident[EI_VERSION] != EV_CURRENT
|
||||
|| hdr->e_version != EV_CURRENT) {
|
||||
link_elf_error("Unsupported file version");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) {
|
||||
if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
|
||||
link_elf_error("Unsupported file type");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
}
|
||||
if (u.hdr.e_machine != ELF_TARG_MACH) {
|
||||
if (hdr->e_machine != ELF_TARG_MACH) {
|
||||
link_elf_error("Unsupported machine");
|
||||
error = ENOEXEC;
|
||||
goto out;
|
||||
@ -474,9 +479,9 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
* not strictly required by the ABI specification, but it seems to
|
||||
* always true in practice. And, it simplifies things considerably.
|
||||
*/
|
||||
if (!((u.hdr.e_phentsize == sizeof(Elf_Phdr))
|
||||
|| (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE)
|
||||
|| (u.hdr.e_phoff + u.hdr.e_phnum*sizeof(Elf_Phdr) <= nbytes)))
|
||||
if (!((hdr->e_phentsize == sizeof(Elf_Phdr)) &&
|
||||
(hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= PAGE_SIZE) &&
|
||||
(hdr->e_phoff + hdr->e_phnum*sizeof(Elf_Phdr) <= nbytes)))
|
||||
link_elf_error("Unreadable program headers");
|
||||
|
||||
/*
|
||||
@ -485,8 +490,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
* We rely on there being exactly two load segments, text and data,
|
||||
* in that order.
|
||||
*/
|
||||
phdr = (Elf_Phdr *) (u.buf + u.hdr.e_phoff);
|
||||
phlimit = phdr + u.hdr.e_phnum;
|
||||
phdr = (Elf_Phdr *) (firstpage + hdr->e_phoff);
|
||||
phlimit = phdr + hdr->e_phnum;
|
||||
nsegs = 0;
|
||||
phdyn = NULL;
|
||||
phphdr = NULL;
|
||||
@ -618,8 +623,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
goto out;
|
||||
|
||||
/* Try and load the symbol table if it's present. (you can strip it!) */
|
||||
nbytes = u.hdr.e_shnum * u.hdr.e_shentsize;
|
||||
if (nbytes == 0 || u.hdr.e_shoff == 0)
|
||||
nbytes = hdr->e_shnum * hdr->e_shentsize;
|
||||
if (nbytes == 0 || hdr->e_shoff == 0)
|
||||
goto nosyms;
|
||||
shdr = malloc(nbytes, M_LINKER, M_WAITOK);
|
||||
if (shdr == NULL) {
|
||||
@ -628,13 +633,13 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
}
|
||||
bzero(shdr, nbytes);
|
||||
error = vn_rdwr(UIO_READ, nd.ni_vp,
|
||||
(caddr_t)shdr, nbytes, u.hdr.e_shoff,
|
||||
(caddr_t)shdr, nbytes, hdr->e_shoff,
|
||||
UIO_SYSSPACE, IO_NODELOCKED, p->p_ucred, &resid, p);
|
||||
if (error)
|
||||
goto out;
|
||||
symtabindex = -1;
|
||||
symstrindex = -1;
|
||||
for (i = 0; i < u.hdr.e_shnum; i++) {
|
||||
for (i = 0; i < hdr->e_shnum; i++) {
|
||||
if (shdr[i].sh_type == SHT_SYMTAB) {
|
||||
symtabindex = i;
|
||||
symstrindex = shdr[i].sh_link;
|
||||
@ -677,6 +682,8 @@ link_elf_load_file(const char* filename, linker_file_t* result)
|
||||
linker_file_unload(lf);
|
||||
if (shdr)
|
||||
free(shdr, M_LINKER);
|
||||
if (firstpage)
|
||||
free(firstpage, M_LINKER);
|
||||
VOP_UNLOCK(nd.ni_vp, 0, p);
|
||||
vn_close(nd.ni_vp, FREAD, p->p_ucred, p);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user