diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/libc/stdlib/malloc.3 | 8 | ||||
-rw-r--r-- | src/lib/libc/stdlib/malloc.c | 49 |
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. | |||
193 | This option requires the library to have been compiled with -DMALLOC_STATS in | 193 | This option requires the library to have been compiled with -DMALLOC_STATS in |
194 | order to have any effect. | 194 | order to have any effect. |
195 | .Pp | 195 | .Pp |
196 | .It Cm G | ||
197 | Enable guard pages and chunk randomization. | ||
198 | Each page size or larger allocation is followed by a guard page that will | ||
199 | cause a segmentation fault upon any access. | ||
200 | Smaller 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 . |
198 | Fill some junk into the area allocated. | 204 | Fill 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) |
11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.63 2003/10/15 21:37:01 tedu Exp $"; | 11 | static 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 ? */ |
194 | static int malloc_realloc; | 194 | static int malloc_realloc; |
195 | 195 | ||
196 | /* mprotect free pages PROT_NONE? */ | ||
197 | static int malloc_freeprot; | ||
198 | |||
199 | /* use guard pages after allocations? */ | ||
200 | static 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 ? */ |
198 | static int malloc_hint; | 204 | static 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) { |