summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortedu <>2003-10-16 17:05:05 +0000
committertedu <>2003-10-16 17:05:05 +0000
commit1874f77dc2bed4915a9ec810e20f905bf3c761fe (patch)
tree0701ccc022b8088a090f2de342f002c592fc744d
parent9c41a5aafdf165f4bfe54930f369850d9425f840 (diff)
downloadopenbsd-1874f77dc2bed4915a9ec810e20f905bf3c761fe.tar.gz
openbsd-1874f77dc2bed4915a9ec810e20f905bf3c761fe.tar.bz2
openbsd-1874f77dc2bed4915a9ec810e20f905bf3c761fe.zip
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.
-rw-r--r--src/lib/libc/stdlib/malloc.38
-rw-r--r--src/lib/libc/stdlib/malloc.c49
2 files changed, 52 insertions, 5 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index 6cbf638173..2af8900656 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -30,7 +30,7 @@
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $OpenBSD: malloc.3,v 1.31 2003/09/26 05:57:02 millert Exp $ 33.\" $OpenBSD: malloc.3,v 1.32 2003/10/16 17:05:04 tedu Exp $
34.\" 34.\"
35.Dd August 27, 1996 35.Dd August 27, 1996
36.Dt MALLOC 3 36.Dt MALLOC 3
@@ -193,6 +193,12 @@ at exit.
193This option requires the library to have been compiled with -DMALLOC_STATS in 193This option requires the library to have been compiled with -DMALLOC_STATS in
194order to have any effect. 194order to have any effect.
195.Pp 195.Pp
196.It Cm G
197Enable guard pages and chunk randomization.
198Each page size or larger allocation is followed by a guard page that will
199cause a segmentation fault upon any access.
200Smaller than page size chunks are returned in a random order.
201.Pp
196.It Cm J 202.It Cm J
197.Dq Junk . 203.Dq Junk .
198Fill some junk into the area allocated. 204Fill some junk into the area allocated.
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c
index 15feb6d2d3..689fa8996a 100644
--- a/src/lib/libc/stdlib/malloc.c
+++ b/src/lib/libc/stdlib/malloc.c
@@ -8,7 +8,7 @@
8 */ 8 */
9 9
10#if defined(LIBC_SCCS) && !defined(lint) 10#if defined(LIBC_SCCS) && !defined(lint)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.63 2003/10/15 21:37:01 tedu Exp $"; 11static char rcsid[] = "$OpenBSD: malloc.c,v 1.64 2003/10/16 17:05:05 tedu Exp $";
12#endif /* LIBC_SCCS and not lint */ 12#endif /* LIBC_SCCS and not lint */
13 13
14/* 14/*
@@ -193,6 +193,12 @@ static int malloc_silent;
193/* always realloc ? */ 193/* always realloc ? */
194static int malloc_realloc; 194static int malloc_realloc;
195 195
196/* mprotect free pages PROT_NONE? */
197static int malloc_freeprot;
198
199/* use guard pages after allocations? */
200static int malloc_guard = 0;
201
196#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 202#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
197/* pass the kernel a hint on free pages ? */ 203/* pass the kernel a hint on free pages ? */
198static int malloc_hint; 204static int malloc_hint;
@@ -386,7 +392,7 @@ map_pages(size_t pages)
386 errno = ENOMEM; 392 errno = ENOMEM;
387 return (NULL); 393 return (NULL);
388 } 394 }
389 tail = result + pages; 395 tail = result + pages + malloc_guard;
390 396
391 if (brk(tail) == (char *)-1) { 397 if (brk(tail) == (char *)-1) {
392#ifdef MALLOC_EXTRA_SANITY 398#ifdef MALLOC_EXTRA_SANITY
@@ -394,6 +400,8 @@ map_pages(size_t pages)
394#endif /* MALLOC_EXTRA_SANITY */ 400#endif /* MALLOC_EXTRA_SANITY */
395 return (NULL); 401 return (NULL);
396 } 402 }
403 if (malloc_guard)
404 mprotect(result + pages, malloc_pagesize, PROT_NONE);
397 405
398 last_index = ptr2index(tail) - 1; 406 last_index = ptr2index(tail) - 1;
399 malloc_brk = tail; 407 malloc_brk = tail;
@@ -500,6 +508,10 @@ malloc_init(void)
500 case 'd': malloc_stats = 0; break; 508 case 'd': malloc_stats = 0; break;
501 case 'D': malloc_stats = 1; break; 509 case 'D': malloc_stats = 1; break;
502#endif /* MALLOC_STATS */ 510#endif /* MALLOC_STATS */
511 case 'f': malloc_freeprot = 0; break;
512 case 'F': malloc_freeprot = 1; break;
513 case 'g': malloc_guard = 0; break;
514 case 'G': malloc_guard = malloc_pagesize; break;
503#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE)) 515#if defined(__FreeBSD__) || (defined(__OpenBSD__) && defined(MADV_FREE))
504 case 'h': malloc_hint = 0; break; 516 case 'h': malloc_hint = 0; break;
505 case 'H': malloc_hint = 1; break; 517 case 'H': malloc_hint = 1; break;
@@ -586,7 +598,7 @@ malloc_pages(size_t size)
586 struct pgfree *pf; 598 struct pgfree *pf;
587 u_long index; 599 u_long index;
588 600
589 size = pageround(size); 601 size = pageround(size) + malloc_guard;
590 602
591 p = NULL; 603 p = NULL;
592 /* Look for free pages before asking for more */ 604 /* Look for free pages before asking for more */
@@ -627,11 +639,16 @@ malloc_pages(size_t size)
627 break; 639 break;
628 } 640 }
629 641
642 size -= malloc_guard;
643
630#ifdef MALLOC_EXTRA_SANITY 644#ifdef MALLOC_EXTRA_SANITY
631 if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE) 645 if (p != NULL && page_dir[ptr2index(p)] != MALLOC_FREE)
632 wrterror("(ES): allocated non-free page on free-list\n"); 646 wrterror("(ES): allocated non-free page on free-list\n");
633#endif /* MALLOC_EXTRA_SANITY */ 647#endif /* MALLOC_EXTRA_SANITY */
634 648
649 if ((malloc_guard || malloc_freeprot) && p != NULL)
650 mprotect(p, size, PROT_READ|PROT_WRITE);
651
635 size >>= malloc_pageshift; 652 size >>= malloc_pageshift;
636 653
637 /* Map new pages */ 654 /* Map new pages */
@@ -798,6 +815,26 @@ malloc_bytes(size_t size)
798 u += u; 815 u += u;
799 k++; 816 k++;
800 } 817 }
818
819 if (malloc_guard) {
820 /* Walk to a random position. */
821 i = arc4random() % bp->free;
822 while (i > 0) {
823 u += u;
824 k++;
825 if (k >= MALLOC_BITS) {
826 lp++;
827 u = 1;
828 k = 0;
829 }
830#ifdef MALLOC_EXTRA_SANITY
831 if (lp - bp->bits > (bp->total - 1) / MALLOC_BITS)
832 wrterror("chunk overflow\n");
833#endif /* MALLOC_EXTRA_SANITY */
834 if (*lp & u)
835 i--;
836 }
837 }
801 *lp ^= u; 838 *lp ^= u;
802 839
803 /* If there are no more free, remove from free-list */ 840 /* If there are no more free, remove from free-list */
@@ -992,13 +1029,17 @@ free_pages(void *ptr, int index, struct pginfo *info)
992 madvise(ptr, l, MADV_FREE); 1029 madvise(ptr, l, MADV_FREE);
993#endif 1030#endif
994 1031
1032 l += malloc_guard;
995 tail = (char *)ptr+l; 1033 tail = (char *)ptr+l;
996 1034
1035 if (malloc_freeprot)
1036 mprotect(ptr, tail - ptr, PROT_NONE);
1037
997 /* add to free-list */ 1038 /* add to free-list */
998 if (px == NULL) 1039 if (px == NULL)
999 px = imalloc(sizeof *px); /* This cannot fail... */ 1040 px = imalloc(sizeof *px); /* This cannot fail... */
1000 px->page = ptr; 1041 px->page = ptr;
1001 px->end = tail; 1042 px->end = tail;
1002 px->size = l; 1043 px->size = l;
1003 1044
1004 if (free_list.next == NULL) { 1045 if (free_list.next == NULL) {