summaryrefslogtreecommitdiff
path: root/src/lib/libc/stdlib/malloc.c
diff options
context:
space:
mode:
authortdeval <>2001-10-30 17:01:07 +0000
committertdeval <>2001-10-30 17:01:07 +0000
commit5bd8dbc6cd62d7e80dc2f37a2cd0b50204573d46 (patch)
tree6896d5d25e2533c5af2ebd5b35227bfa4624c76a /src/lib/libc/stdlib/malloc.c
parentf059999eca50fb7d7f0568e426f8b54acf8d325e (diff)
downloadopenbsd-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.c83
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)
11static char rcsid[] = "$OpenBSD: malloc.c,v 1.42 2001/05/11 15:30:14 art Exp $"; 11static 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);