summaryrefslogtreecommitdiff
path: root/lib/libc
diff options
context:
space:
mode:
authorThierry Deval <tdeval@cvs.openbsd.org>2001-10-30 17:01:08 +0000
committerThierry Deval <tdeval@cvs.openbsd.org>2001-10-30 17:01:08 +0000
commitcff78495d772d9c669dc7124429f3ac11c072502 (patch)
tree7c635534b43b1023f401d24251f157a5405b66c7 /lib/libc
parentf6c16da93ee22d0e0e6fc7df6358728fab7778a0 (diff)
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 'lib/libc')
-rw-r--r--lib/libc/shlib_version2
-rw-r--r--lib/libc/stdlib/malloc.34
-rw-r--r--lib/libc/stdlib/malloc.c83
3 files changed, 51 insertions, 38 deletions
diff --git a/lib/libc/shlib_version b/lib/libc/shlib_version
index e10615e1a3b..b7d2c248618 100644
--- a/lib/libc/shlib_version
+++ b/lib/libc/shlib_version
@@ -1,2 +1,2 @@
major=28
-minor=1 # note: remember to update minor in ../libc_r/shlib_version
+minor=2 # note: remember to update minor in ../libc_r/shlib_version
diff --git a/lib/libc/stdlib/malloc.3 b/lib/libc/stdlib/malloc.3
index e65668566e6..2f7e0c61b52 100644
--- a/lib/libc/stdlib/malloc.3
+++ b/lib/libc/stdlib/malloc.3
@@ -34,7 +34,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $OpenBSD: malloc.3,v 1.20 2000/10/25 15:23:15 aaron Exp $
+.\" $OpenBSD: malloc.3,v 1.21 2001/10/30 17:01:07 tdeval Exp $
.\"
.Dd August 27, 1996
.Dt MALLOC 3
@@ -79,6 +79,8 @@ If the space is of
or larger, the memory returned will be page-aligned.
.Pp
Allocation of a zero size object returns a pointer to a zero size object.
+This zero size object is access protected, so any access to it will
+generate an exception (SIGSEGV)
.Pp
The
.Fn calloc
diff --git a/lib/libc/stdlib/malloc.c b/lib/libc/stdlib/malloc.c
index deef086428a..3833bab5f9c 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.42 2001/05/11 15:30:14 art Exp $";
+static char rcsid[] = "$OpenBSD: malloc.c,v 1.43 2001/10/30 17:01:07 tdeval Exp $";
#endif /* LIBC_SCCS and not lint */
/*
@@ -63,28 +63,8 @@ static char rcsid[] = "$OpenBSD: malloc.c,v 1.42 2001/05/11 15:30:14 art Exp $";
*
*/
-#if defined(__i386__) && defined(__FreeBSD__)
-# define malloc_pageshift 12U
-# define malloc_minsize 16U
-#endif /* __i386__ && __FreeBSD__ */
-
-#if defined(__sparc__) && !defined(__OpenBSD__)
-# define malloc_pageshift 12U
-# define malloc_minsize 16U
-# define MAP_ANON (0)
-# define USE_DEV_ZERO
-# define MADV_FREE MADV_DONTNEED
-#endif /* __sparc__ */
-
-/* Insert your combination here... */
-#if defined(__FOOCPU__) && defined(__BAROS__)
-# define malloc_pageshift 12U
-# define malloc_minsize 16U
-#endif /* __FOOCPU__ && __BAROS__ */
-
-#if defined(__OpenBSD__) && !defined(__sparc__)
-# define malloc_pageshift (PGSHIFT)
-# define malloc_minsize 16U
+#if defined(__OpenBSD__) && defined(__sparc__)
+# define malloc_pageshift 13U
#endif /* __OpenBSD__ */
#ifdef _THREAD_SAFE
@@ -164,7 +144,7 @@ struct pgfree {
#define MALLOC_MAGIC ((struct pginfo*) 4)
#ifndef malloc_pageshift
-#define malloc_pageshift 12U
+#define malloc_pageshift (PGSHIFT)
#endif
#ifndef malloc_minsize
@@ -730,7 +710,13 @@ malloc_make_chunks(bits)
(((malloc_pagesize >> bits)+MALLOC_BITS-1) / MALLOC_BITS);
/* Don't waste more than two chunks on this */
- if ((1UL<<(bits)) <= l+l) {
+ /*
+ * If we are to allocate a memory protected page for the malloc(0)
+ * case (when bits=0), it must be from a different page than the
+ * pginfo page.
+ * --> Treat it like the big chunk alloc, get a second data page.
+ */
+ if (bits != 0 && (1UL<<(bits)) <= l+l) {
bp = (struct pginfo *)pp;
} else {
bp = (struct pginfo *)imalloc(l);
@@ -745,6 +731,16 @@ malloc_make_chunks(bits)
bp->total = bp->free = malloc_pagesize >> bits;
bp->page = pp;
+ /* memory protect the page allocated in the malloc(0) case */
+ if (bits == 0) {
+ k = mprotect(pp, malloc_pagesize, PROT_NONE);
+ if (k < 0) {
+ ifree(pp);
+ ifree(bp);
+ return 0;
+ }
+ }
+
/* set all valid bits in the bitmap */
k = bp->total;
i = 0;
@@ -792,14 +788,19 @@ malloc_bytes(size)
u_long *lp;
/* Don't bother with anything less than this */
- if (size < malloc_minsize)
+ /* unless we have a malloc(0) requests */
+ if (size != 0 && size < malloc_minsize)
size = malloc_minsize;
/* Find the right bucket */
- j = 1;
- i = size-1;
- while (i >>= 1)
- j++;
+ if (size == 0)
+ j=0;
+ else {
+ j = 1;
+ i = size-1;
+ while (i >>= 1)
+ j++;
+ }
/* If it's empty, make a page more of that size chunks */
if (!page_dir[j] && !malloc_make_chunks(j))
@@ -830,7 +831,7 @@ malloc_bytes(size)
k += (lp-bp->bits)*MALLOC_BITS;
k <<= bp->shift;
- if (malloc_junk)
+ if (malloc_junk && bp->shift != 0)
memset((char *)bp->page + k, SOME_JUNK, bp->size);
return (u_char *)bp->page + k;
@@ -955,10 +956,13 @@ irealloc(ptr, size)
if (p) {
/* copy the lesser of the two sizes, and free the old one */
- if (osize < size)
- memcpy(p, ptr, osize);
- else
- memcpy(p, ptr, size);
+ /* Don't move from/to 0 sized region !!! */
+ if (osize != 1 && size != 0) {
+ if (osize < size)
+ memcpy(p, ptr, osize);
+ else
+ memcpy(p, ptr, size);
+ }
ifree(ptr);
}
return p;
@@ -1127,7 +1131,7 @@ free_bytes(ptr, index, info)
return;
}
- if (malloc_junk)
+ if (malloc_junk && info->shift != 0)
memset(ptr, SOME_JUNK, info->size);
info->bits[i/MALLOC_BITS] |= 1UL<<(i%MALLOC_BITS);
@@ -1163,6 +1167,13 @@ free_bytes(ptr, index, info)
/* Free the page & the info structure if need be */
page_dir[ptr2index(info->page)] = MALLOC_FIRST;
+
+ /* If the page was mprotected, unprotect it before releasing it */
+ if (info->shift == 0) {
+ mprotect(info->page, malloc_pagesize, PROT_READ|PROT_WRITE);
+ /* Do we have to care if mprotect succeeds here ? */
+ }
+
vp = info->page; /* Order is important ! */
if(vp != (void*)info)
ifree(info);