Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern Properly check the section size to avoid out-of-bou...
details: https://anonhg.NetBSD.org/src/rev/d8e75f488e1e
branches: trunk
changeset: 326878:d8e75f488e1e
user: maxv <maxv%NetBSD.org@localhost>
date: Fri Feb 21 07:47:02 2014 +0000
description:
Properly check the section size to avoid out-of-bound reads. The
computed size must be the exact same size that is indicated in
sh_size.
ok agc@ christos@
diffstat:
sys/kern/exec_elf.c | 31 ++++++++++++++++++++++---------
1 files changed, 22 insertions(+), 9 deletions(-)
diffs (82 lines):
diff -r 02deee5b1839 -r d8e75f488e1e sys/kern/exec_elf.c
--- a/sys/kern/exec_elf.c Fri Feb 21 07:32:43 2014 +0000
+++ b/sys/kern/exec_elf.c Fri Feb 21 07:47:02 2014 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_elf.c,v 1.59 2014/02/19 15:23:20 maxv Exp $ */
+/* $NetBSD: exec_elf.c,v 1.60 2014/02/21 07:47:02 maxv 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.59 2014/02/19 15:23:20 maxv Exp $");
+__KERNEL_RCSID(1, "$NetBSD: exec_elf.c,v 1.60 2014/02/21 07:47:02 maxv Exp $");
#ifdef _KERNEL_OPT
#include "opt_pax.h"
@@ -873,7 +873,7 @@
size_t i;
Elf_Shdr *sh;
Elf_Nhdr *np;
- size_t shsize;
+ size_t shsize, nsize;
int error;
int isnetbsd = 0;
char *ndata;
@@ -902,11 +902,23 @@
if (error)
continue;
+ /* Point to the note, skip the header */
ndata = (char *)(np + 1);
- unsigned int maxlen = (unsigned int)(shp->sh_size -
- ((char *)ndata - (char *)np));
- if (maxlen < np->n_namesz)
+
+ /*
+ * Padding is present if necessary to ensure 4-byte alignment.
+ * The actual section size is therefore:
+ * header size + 4-byte aligned name + 4-byte aligned desc
+ * Ensure this size is consistent with what is indicated
+ * in sh_size. The first check avoids integer overflows.
+ */
+ if (np->n_namesz > shp->sh_size || np->n_descsz > shp->sh_size)
goto bad;
+ nsize = sizeof(*np) + roundup(np->n_namesz, 4) +
+ roundup(np->n_descsz, 4);
+ if (nsize != shp->sh_size)
+ goto bad;
+
switch (np->n_type) {
case ELF_NOTE_TYPE_NETBSD_TAG:
/*
@@ -917,7 +929,7 @@
memcmp(ndata, ELF_NOTE_NETBSD_NAME,
ELF_NOTE_NETBSD_NAMESZ) == 0) {
memcpy(&epp->ep_osversion,
- ndata + ELF_NOTE_NETBSD_NAMESZ + 1,
+ ndata + roundup(ELF_NOTE_NETBSD_NAMESZ, 4),
ELF_NOTE_NETBSD_DESCSZ);
isnetbsd = 1;
break;
@@ -949,7 +961,8 @@
memcmp(ndata, ELF_NOTE_GNU_NAME,
ELF_NOTE_GNU_NAMESZ) == 0)
break;
- int ns = MIN(np->n_namesz, maxlen);
+
+ int ns = MIN(np->n_namesz, shp->sh_size - sizeof(*np));
printf("%s: Unknown elf note type %d: "
"[namesz=%d, descsz=%d name=%*.*s]\n",
epp->ep_kname, np->n_type, np->n_namesz,
@@ -959,7 +972,7 @@
continue;
}
(void)memcpy(&epp->ep_pax_flags,
- ndata + ELF_NOTE_PAX_NAMESZ,
+ ndata + roundup(ELF_NOTE_PAX_NAMESZ, 4),
sizeof(epp->ep_pax_flags));
break;
Home |
Main Index |
Thread Index |
Old Index