Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern - Make maximum memory limits for various things #de...
details: https://anonhg.NetBSD.org/src/rev/58bceebd67be
branches: trunk
changeset: 753191:58bceebd67be
user: christos <christos%NetBSD.org@localhost>
date: Fri Mar 19 22:08:13 2010 +0000
description:
- Make maximum memory limits for various things #define constants and use the
consistently across the code.
- Re-do note parsing code to read the section headers instead of the program
headers because the new binutils merge all the note sections in one program
header. This fixes all the pax note parsing which has been broken for all
binaries built with the new binutils.
- Add diagnostics to the note parsing code to detect malformed binaries.
- Allocate and free note scratch space only once, not once per note.
diffstat:
sys/kern/exec_elf.c | 124 +++++++++++++++++++++++++++++++--------------------
1 files changed, 74 insertions(+), 50 deletions(-)
diffs (211 lines):
diff -r 8ce9e09051bc -r 58bceebd67be sys/kern/exec_elf.c
--- a/sys/kern/exec_elf.c Fri Mar 19 20:53:50 2010 +0000
+++ b/sys/kern/exec_elf.c Fri Mar 19 22:08:13 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_elf.c,v 1.14 2010/03/15 20:35:20 christos Exp $ */
+/* $NetBSD: exec_elf.c,v 1.15 2010/03/19 22:08:13 christos Exp $ */
/*-
* Copyright (c) 1994, 2000, 2005 The NetBSD Foundation, Inc.
@@ -57,7 +57,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.14 2010/03/15 20:35:20 christos Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.15 2010/03/19 22:08:13 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_pax.h"
@@ -109,7 +109,12 @@
#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1))
#define ELF_TRUNC(a, b) ((a) & ~((b) - 1))
-#define MAXPHNUM 50
+/*
+ * Arbitrary limits to avoid DoS for excessive memory allocation.
+ */
+#define MAXPHNUM 128
+#define MAXSHNUM 32768
+#define MAXNOTESIZE 1024
#ifdef PAX_ASLR
/*
@@ -119,33 +124,35 @@
pax_aslr_elf(struct lwp *l, struct exec_package *epp, Elf_Ehdr *eh,
Elf_Phdr *ph)
{
- size_t pax_align = 0, pax_offset, i;
- uint32_t r;
+ size_t pax_offset, i;
- if (!pax_aslr_active(l))
- return;
+ if (pax_aslr_active(l)) {
+ size_t pax_align, l2, delta;
+ uint32_t r;
- /*
- * find align XXX: not all sections might have the same
- * alignment
- */
- for (i = 0; i < eh->e_phnum; i++)
- if (ph[i].p_type == PT_LOAD) {
- pax_align = ph[i].p_align;
- break;
- }
+ /*
+ * find align XXX: not all sections might have the same
+ * alignment
+ */
+ for (pax_align = i = 0; i < eh->e_phnum; i++)
+ if (ph[i].p_type == PT_LOAD) {
+ pax_align = ph[i].p_align;
+ break;
+ }
+
+ r = arc4random();
- r = arc4random();
-
- if (pax_align == 0)
- pax_align = PGSHIFT;
+ if (pax_align == 0)
+ pax_align = PGSHIFT;
+ l2 = ilog2(pax_align);
+ delta = PAX_ASLR_DELTA(r, l2, PAX_ASLR_DELTA_EXEC_LEN);
#ifdef PAX_ASLR_DEBUG
- uprintf("r=0x%x a=0x%x p=0x%x Delta=0x%lx\n", r,
- ilog2(pax_align), PGSHIFT, PAX_ASLR_DELTA(r,
- ilog2(pax_align), PAX_ASLR_DELTA_EXEC_LEN));
+ uprintf("r=0x%x a=0x%x p=0x%x Delta=0x%lx\n", r, l2, PGSHIFT,
+ delta);
#endif
- pax_offset = ELF_TRUNC(PAX_ASLR_DELTA(r,
- ilog2(pax_align), PAX_ASLR_DELTA_EXEC_LEN), pax_align) + PAGE_SIZE;
+ pax_offset = ELF_TRUNC(delta, pax_align) + PAGE_SIZE;
+ } else
+ pax_offset = PAGE_SIZE;
for (i = 0; i < eh->e_phnum; i++)
ph[i].p_vaddr += pax_offset;
@@ -303,7 +310,7 @@
if (eh->e_type != type)
return ENOEXEC;
- if (eh->e_shnum > 32768 || eh->e_phnum > 128)
+ if (eh->e_shnum > MAXSHNUM || eh->e_phnum > MAXPHNUM)
return ENOEXEC;
return 0;
@@ -845,36 +852,36 @@
Elf_Ehdr *eh)
{
size_t i;
- Elf_Phdr *ph;
- size_t phsize;
+ Elf_Shdr *sh;
+ Elf_Nhdr *np;
+ size_t shsize;
int error;
int isnetbsd = 0;
char *ndata;
epp->ep_pax_flags = 0;
- if (eh->e_phnum > MAXPHNUM || eh->e_phnum == 0)
+ if (eh->e_shnum > MAXSHNUM || eh->e_shnum == 0)
return ENOEXEC;
- phsize = eh->e_phnum * sizeof(Elf_Phdr);
- ph = kmem_alloc(phsize, KM_SLEEP);
- error = exec_read_from(l, epp->ep_vp, eh->e_phoff, ph, phsize);
+ shsize = eh->e_shnum * sizeof(Elf_Shdr);
+ sh = kmem_alloc(shsize, KM_SLEEP);
+ error = exec_read_from(l, epp->ep_vp, eh->e_shoff, sh, shsize);
if (error)
goto out;
- for (i = 0; i < eh->e_phnum; i++) {
- Elf_Phdr *ephp = &ph[i];
- Elf_Nhdr *np;
+ np = kmem_alloc(MAXNOTESIZE, KM_SLEEP);
+ for (i = 0; i < eh->e_shnum; i++) {
+ Elf_Shdr *shp = &sh[i];
- if (ephp->p_type != PT_NOTE ||
- ephp->p_filesz > 1024 ||
- ephp->p_filesz < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
+ if (shp->sh_type != SHT_NOTE ||
+ shp->sh_size > MAXNOTESIZE ||
+ shp->sh_size < sizeof(Elf_Nhdr) + ELF_NOTE_NETBSD_NAMESZ)
continue;
- np = kmem_alloc(ephp->p_filesz, KM_SLEEP);
- error = exec_read_from(l, epp->ep_vp, ephp->p_offset, np,
- ephp->p_filesz);
+ error = exec_read_from(l, epp->ep_vp, shp->sh_offset, np,
+ shp->sh_size);
if (error)
- goto next;
+ continue;
ndata = (char *)(np + 1);
switch (np->n_type) {
@@ -883,7 +890,7 @@
np->n_descsz != ELF_NOTE_NETBSD_DESCSZ ||
memcmp(ndata, ELF_NOTE_NETBSD_NAME,
ELF_NOTE_NETBSD_NAMESZ))
- goto next;
+ goto bad;
isnetbsd = 1;
break;
@@ -891,25 +898,42 @@
if (np->n_namesz != ELF_NOTE_PAX_NAMESZ ||
np->n_descsz != ELF_NOTE_PAX_DESCSZ ||
memcmp(ndata, ELF_NOTE_PAX_NAME,
- ELF_NOTE_PAX_NAMESZ))
- goto next;
+ ELF_NOTE_PAX_NAMESZ)) {
+bad:
+#ifdef DIAGNOSTIC
+ printf("%s: bad tag %d: "
+ "[%d %d, %d %d, %*.*s %*.*s]\n",
+ epp->ep_name,
+ np->n_type
+ np->n_namesz, ELF_NOTE_PAX_NAMESZ,
+ np->n_descsz, ELF_NOTE_PAX_DESCSZ,
+ ELF_NOTE_PAX_NAMESZ,
+ ELF_NOTE_PAX_NAMESZ,
+ ndata,
+ ELF_NOTE_PAX_NAMESZ,
+ ELF_NOTE_PAX_NAMESZ,
+ ELF_NOTE_PAX_NAME);
+#endif
+ continue;
+ }
(void)memcpy(&epp->ep_pax_flags,
ndata + ELF_NOTE_PAX_NAMESZ,
sizeof(epp->ep_pax_flags));
break;
default:
+#ifdef DIAGNOSTIC
+ printf("%s: unknown note type %d\n", epp->ep_name,
+ np->n_type);
+#endif
break;
}
-
-next:
- kmem_free(np, ephp->p_filesz);
- continue;
}
+ kmem_free(np, MAXNOTESIZE);
error = isnetbsd ? 0 : ENOEXEC;
out:
- kmem_free(ph, phsize);
+ kmem_free(sh, shsize);
return error;
}
Home |
Main Index |
Thread Index |
Old Index