summaryrefslogtreecommitdiff
path: root/lib/libc/stdlib
diff options
context:
space:
mode:
authorTed Unangst <tedu@cvs.openbsd.org>2003-10-16 17:05:06 +0000
committerTed Unangst <tedu@cvs.openbsd.org>2003-10-16 17:05:06 +0000
commitb3fb36e241c10f88ff39c1fde2c2f0bfea706bea (patch)
tree34be23dbebc7d9e36d67d10caed00e2b21997aa4 /lib/libc/stdlib
parent233fac375b1bbd3ad1a7fb89dfc40fd98e386bdb (diff)
by popular demand, malloc guard pages. insert an unreadable/unwriteable
page after each page size allocation to detect overrun. this is somewhat electric fence like, while attempting to be mostly usable in production. also, use tdeval's chunk randomization code. enabled with the G option. ok deraadt and co.
Diffstat (limited to 'lib/libc/stdlib')
-rw-r--r--lib/libc/stdlib/malloc.38
-rw-r--r--lib/libc/stdlib/malloc.c49
2 files changed, 52 insertions, 5 deletions
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3
index 6cbf6381738..2af89006560 100644
--- a/lib/libc/stdlib/malloc.3
+++ b/lib/libc/stdlib/malloc.3
@@ -30,7 +30,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $OpenBSD: malloc.3,v 1.31 2003/09/26 05:57:02 millert Exp $
+.\" $OpenBSD: malloc.3,v 1.32 2003/10/16 17:05:04 tedu Exp $
.\"
.Dd August 27, 1996
.Dt MALLOC 3
@@ -193,6 +193,12 @@ at exit.
This option requires the library to have been compiled with -DMALLOC_STATS in
order to have any effect.
.Pp
+.It Cm G
+Enable guard pages and chunk randomization.
+Each page size or larger allocation is followed by a guard page that will
+cause a segmentation fault upon any access.
+Smaller than page size chunks are returned in a random order.
+.Pp
.It Cm J
.Dq Junk .
Fill some junk into the area allocated.
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index 15feb6d2d38..689fa8996ae 100644
--- a/lib/libc/stdlib/malloc.c
+++ b/lib/libc/stdlib/malloc.c
@@ -8,7 +8,7 @@
*/
#if defined(LIBC_SCCS) && !defined(lint)
-static char rcsid[] = "$OpenBSD: malloc.c,v 1.63 2003/10/15 21:37:01 tedu Exp $";
+static char rcsid[] = "$OpenBSD: malloc.c,v 1.64 2003/10/16 17:05:05 tedu Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -193,6 +193,12 @@ static int malloc_silent;
/* always realloc ? */
static int malloc_realloc;
+/* mprotect free pages PROT_NONE? */
+static int malloc_freeprot;
+
+/* use guard pages after allocations? */
+static int malloc_guard = 0;
+
#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
/* pass the kernel a hint on free pages ? */
static int malloc_hint;
@@ -386,7 +392,7 @@ map_pages(size_t pages)
errno = ENOMEM;
return (NULL);
}
- tail = result + pages;
+ tail = result + pages + malloc_guard;
if (brk(tail) == (char *)-1) {
#ifdef MALLOC_EXTRA_SANITY
@@ -394,6 +400,8 @@ map_pages(size_t pages)
#endif /* MALLOC_EXTRA_SANITY */
return (NULL);
}
+ if (malloc_guard)
+ mprotect(result + pages, malloc_pagesize, PROT_NONE);
last_index = ptr2index(tail) - 1;
malloc_brk = tail;
@@ -500,6 +508,10 @@ malloc_init(void)
case 'd': malloc_stats = 0; break;
case 'D': malloc_stats = 1; break;
#endif /* MALLOC_STATS */
+ case 'f': malloc_freeprot = 0; break;
+ case 'F': malloc_freeprot = 1; break;
+ case 'g': malloc_guard = 0; break;
+ case 'G': malloc_guard = malloc_pagesize; break;
#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
case 'h': malloc_hint = 0; break;
case 'H': malloc_hint = 1; break;
@@ -586,7 +598,7 @@ malloc_pages(size_t size)
struct pgfree *pf;
u_long index;
- size = pageround(size);
+ size = pageround(size) + malloc_guard;
p = NULL;
/* Look for free pages before asking for more */
@@ -627,11 +639,16 @@ malloc_pages(size_t size)
break;
}
+ size -= malloc_guard;
+
#ifdef MALLOC_EXTRA_SANITY
if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE)
wrterror("(ES): allocated non-free page on free-list\n");
#endif /* MALLOC_EXTRA_SANITY */
+ if ((malloc_guard || malloc_freeprot) && p != NULL)
+ mprotect(p, size, PROT_READ|PROT_WRITE);
+
size >>= malloc_pageshift;
/* Map new pages */
@@ -798,6 +815,26 @@ malloc_bytes(size_t size)
u += u;
k++;
}
+
+ if (malloc_guard) {
+ /* Walk to a random position. */
+ i = arc4random() % bp->free;
+ while (i > 0) {
+ u += u;
+ k++;
+ if (k >= MALLOC_BITS) {
+ lp++;
+ u = 1;
+ k = 0;
+ }
+#ifdef MALLOC_EXTRA_SANITY
+ if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
+ wrterror("chunk overflow\n");
+#endif /* MALLOC_EXTRA_SANITY */
+ if (*lp & u)
+ i--;
+ }
+ }
*lp ^= u;
/* If there are no more free, remove from free-list */
@@ -992,13 +1029,17 @@ free_pages(void *ptr, int index, struct pginfo *info)
madvise(ptr, l, MADV_FREE);
#endif
+ l += malloc_guard;
tail = (char *)ptr+l;
+ if (malloc_freeprot)
+ mprotect(ptr, tail - ptr, PROT_NONE);
+
/* add to free-list */
if (px == NULL)
px = imalloc(sizeof *px); /* This cannot fail... */
px->page = ptr;
- px->end = tail;
+ px->end = tail;
px->size = l;
if (free_list.next == NULL) {