diff options
author | peter <peter@FreeBSD.org> | 1998-11-06 15:16:07 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-11-06 15:16:07 +0000 |
commit | b5f83c161eae3fd27e934fe40a00f9f32869b1f9 (patch) | |
tree | 20926f39199ce68c7583c563deea7f21e9b29d10 /sys | |
parent | d620d61682ae13ad87adef81b40487e5949ed660 (diff) | |
download | FreeBSD-src-b5f83c161eae3fd27e934fe40a00f9f32869b1f9.zip FreeBSD-src-b5f83c161eae3fd27e934fe40a00f9f32869b1f9.tar.gz |
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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/link_elf.c | 53 | ||||
-rw-r--r-- | sys/kern/link_elf_obj.c | 53 |
2 files changed, 60 insertions, 46 deletions
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 6f9a578..132fc87 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -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 @@ out: 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); diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 6f9a578..132fc87 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -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 @@ out: 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); |