diff options
| author | tdeval <> | 2001-10-30 17:01:07 +0000 |
|---|---|---|
| committer | tdeval <> | 2001-10-30 17:01:07 +0000 |
| commit | 5bd8dbc6cd62d7e80dc2f37a2cd0b50204573d46 (patch) | |
| tree | 6896d5d25e2533c5af2ebd5b35227bfa4624c76a /src/lib/libc/stdlib/malloc.c | |
| parent | f059999eca50fb7d7f0568e426f8b54acf8d325e (diff) | |
| download | openbsd-5bd8dbc6cd62d7e80dc2f37a2cd0b50204573d46.tar.gz openbsd-5bd8dbc6cd62d7e80dc2f37a2cd0b50204573d46.tar.bz2 openbsd-5bd8dbc6cd62d7e80dc2f37a2cd0b50204573d46.zip | |
mprotect allocations sized at 0 bytes. This will cause a fault for access
to such, permitting them to be discovered, instead of exploited as the ssh
crc insertion detector was. Idea by theo, written by tdeval.
Diffstat (limited to 'src/lib/libc/stdlib/malloc.c')
| -rw-r--r-- | src/lib/libc/stdlib/malloc.c | 83 |
1 files changed, 47 insertions, 36 deletions
diff --git a/src/lib/libc/stdlib/malloc.c b/src/lib/libc/stdlib/malloc.c index deef086428..3833bab5f9 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.42 2001/05/11 15:30:14 art Exp $"; | 11 | static char rcsid[] = "$OpenBSD: malloc.c,v 1.43 2001/10/30 17:01:07 tdeval Exp $"; |
| 12 | #endif /* LIBC_SCCS and not lint */ | 12 | #endif /* LIBC_SCCS and not lint */ |
| 13 | 13 | ||
| 14 | /* | 14 | /* |
| @@ -63,28 +63,8 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.42 2001/05/11 15:30:14 art Exp $"; | |||
| 63 | * | 63 | * |
| 64 | */ | 64 | */ |
| 65 | 65 | ||
| 66 | #if defined(__i386__) && defined(__FreeBSD__) | 66 | #if defined(__OpenBSD__) && defined(__sparc__) |
| 67 | # define malloc_pageshift 12U | 67 | # define malloc_pageshift 13U |
| 68 | # define malloc_minsize 16U | ||
| 69 | #endif /* __i386__ && __FreeBSD__ */ | ||
| 70 | |||
| 71 | #if defined(__sparc__) && !defined(__OpenBSD__) | ||
| 72 | # define malloc_pageshift 12U | ||
| 73 | # define malloc_minsize 16U | ||
| 74 | # define MAP_ANON (0) | ||
| 75 | # define USE_DEV_ZERO | ||
| 76 | # define MADV_FREE MADV_DONTNEED | ||
| 77 | #endif /* __sparc__ */ | ||
| 78 | |||
| 79 | /* Insert your combination here... */ | ||
| 80 | #if defined(__FOOCPU__) && defined(__BAROS__) | ||
| 81 | # define malloc_pageshift 12U | ||
| 82 | # define malloc_minsize 16U | ||
| 83 | #endif /* __FOOCPU__ && __BAROS__ */ | ||
| 84 | |||
| 85 | #if defined(__OpenBSD__) && !defined(__sparc__) | ||
| 86 | # define malloc_pageshift (PGSHIFT) | ||
| 87 | # define malloc_minsize 16U | ||
| 88 | #endif /* __OpenBSD__ */ | 68 | #endif /* __OpenBSD__ */ |
| 89 | 69 | ||
| 90 | #ifdef _THREAD_SAFE | 70 | #ifdef _THREAD_SAFE |
| @@ -164,7 +144,7 @@ struct pgfree { | |||
| 164 | #define MALLOC_MAGIC ((struct pginfo*) 4) | 144 | #define MALLOC_MAGIC ((struct pginfo*) 4) |
| 165 | 145 | ||
| 166 | #ifndef malloc_pageshift | 146 | #ifndef malloc_pageshift |
| 167 | #define malloc_pageshift 12U | 147 | #define malloc_pageshift (PGSHIFT) |
| 168 | #endif | 148 | #endif |
| 169 | 149 | ||
| 170 | #ifndef malloc_minsize | 150 | #ifndef malloc_minsize |
| @@ -730,7 +710,13 @@ malloc_make_chunks(bits) | |||
| 730 | (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS); | 710 | (((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS); |
| 731 | 711 | ||
| 732 | /* Don't waste more than two chunks on this */ | 712 | /* Don't waste more than two chunks on this */ |
| 733 | if ((1UL<<(bits)) <= l+l) { | 713 | /* |
| 714 | * If we are to allocate a memory protected page for the malloc(0) | ||
| 715 | * case (when bits=0), it must be from a different page than the | ||
| 716 | * pginfo page. | ||
| 717 | * --> Treat it like the big chunk alloc, get a second data page. | ||
| 718 | */ | ||
| 719 | if (bits != 0 && (1UL<<(bits)) <= l+l) { | ||
| 734 | bp = (struct pginfo *)pp; | 720 | bp = (struct pginfo *)pp; |
| 735 | } else { | 721 | } else { |
| 736 | bp = (struct pginfo *)imalloc(l); | 722 | bp = (struct pginfo *)imalloc(l); |
| @@ -745,6 +731,16 @@ malloc_make_chunks(bits) | |||
| 745 | bp->total = bp->free = malloc_pagesize >> bits; | 731 | bp->total = bp->free = malloc_pagesize >> bits; |
| 746 | bp->page = pp; | 732 | bp->page = pp; |
| 747 | 733 | ||
| 734 | /* memory protect the page allocated in the malloc(0) case */ | ||
| 735 | if (bits == 0) { | ||
| 736 | k = mprotect(pp, malloc_pagesize, PROT_NONE); | ||
| 737 | if (k < 0) { | ||
| 738 | ifree(pp); | ||
| 739 | ifree(bp); | ||
| 740 | return 0; | ||
| 741 | } | ||
| 742 | } | ||
| 743 | |||
| 748 | /* set all valid bits in the bitmap */ | 744 | /* set all valid bits in the bitmap */ |
| 749 | k = bp->total; | 745 | k = bp->total; |
| 750 | i = 0; | 746 | i = 0; |
| @@ -792,14 +788,19 @@ malloc_bytes(size) | |||
| 792 | u_long *lp; | 788 | u_long *lp; |
| 793 | 789 | ||
| 794 | /* Don't bother with anything less than this */ | 790 | /* Don't bother with anything less than this */ |
| 795 | if (size < malloc_minsize) | 791 | /* unless we have a malloc(0) requests */ |
| 792 | if (size != 0 && size < malloc_minsize) | ||
| 796 | size = malloc_minsize; | 793 | size = malloc_minsize; |
| 797 | 794 | ||
| 798 | /* Find the right bucket */ | 795 | /* Find the right bucket */ |
| 799 | j = 1; | 796 | if (size == 0) |
| 800 | i = size-1; | 797 | j=0; |
| 801 | while (i >>= 1) | 798 | else { |
| 802 | j++; | 799 | j = 1; |
| 800 | i = size-1; | ||
| 801 | while (i >>= 1) | ||
| 802 | j++; | ||
| 803 | } | ||
| 803 | 804 | ||
| 804 | /* If it's empty, make a page more of that size chunks */ | 805 | /* If it's empty, make a page more of that size chunks */ |
| 805 | if (!page_dir[j] && !malloc_make_chunks(j)) | 806 | if (!page_dir[j] && !malloc_make_chunks(j)) |
| @@ -830,7 +831,7 @@ malloc_bytes(size) | |||
| 830 | k += (lp-bp->bits)*MALLOC_BITS; | 831 | k += (lp-bp->bits)*MALLOC_BITS; |
| 831 | k <<= bp->shift; | 832 | k <<= bp->shift; |
| 832 | 833 | ||
| 833 | if (malloc_junk) | 834 | if (malloc_junk && bp->shift != 0) |
| 834 | memset((char *)bp->page + k, SOME_JUNK, bp->size); | 835 | memset((char *)bp->page + k, SOME_JUNK, bp->size); |
| 835 | 836 | ||
| 836 | return (u_char *)bp->page + k; | 837 | return (u_char *)bp->page + k; |
| @@ -955,10 +956,13 @@ irealloc(ptr, size) | |||
| 955 | 956 | ||
| 956 | if (p) { | 957 | if (p) { |
| 957 | /* copy the lesser of the two sizes, and free the old one */ | 958 | /* copy the lesser of the two sizes, and free the old one */ |
| 958 | if (osize < size) | 959 | /* Don't move from/to 0 sized region !!! */ |
| 959 | memcpy(p, ptr, osize); | 960 | if (osize != 1 && size != 0) { |
| 960 | else | 961 | if (osize < size) |
| 961 | memcpy(p, ptr, size); | 962 | memcpy(p, ptr, osize); |
| 963 | else | ||
| 964 | memcpy(p, ptr, size); | ||
| 965 | } | ||
| 962 | ifree(ptr); | 966 | ifree(ptr); |
| 963 | } | 967 | } |
| 964 | return p; | 968 | return p; |
| @@ -1127,7 +1131,7 @@ free_bytes(ptr, index, info) | |||
| 1127 | return; | 1131 | return; |
| 1128 | } | 1132 | } |
| 1129 | 1133 | ||
| 1130 | if (malloc_junk) | 1134 | if (malloc_junk && info->shift != 0) |
| 1131 | memset(ptr, SOME_JUNK, info->size); | 1135 | memset(ptr, SOME_JUNK, info->size); |
| 1132 | 1136 | ||
| 1133 | info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS); | 1137 | info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS); |
| @@ -1163,6 +1167,13 @@ free_bytes(ptr, index, info) | |||
| 1163 | 1167 | ||
| 1164 | /* Free the page & the info structure if need be */ | 1168 | /* Free the page & the info structure if need be */ |
| 1165 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; | 1169 | page_dir[ptr2index(info->page)] = MALLOC_FIRST; |
| 1170 | |||
| 1171 | /* If the page was mprotected, unprotect it before releasing it */ | ||
| 1172 | if (info->shift == 0) { | ||
| 1173 | mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE); | ||
| 1174 | /* Do we have to care if mprotect succeeds here ? */ | ||
| 1175 | } | ||
| 1176 | |||
| 1166 | vp = info->page; /* Order is important ! */ | 1177 | vp = info->page; /* Order is important ! */ |
| 1167 | if(vp != (void*)info) | 1178 | if(vp != (void*)info) |
| 1168 | ifree(info); | 1179 | ifree(info); |
