From 64c3fdb4f6f9d1c7aae94078345b946ca050b001 Mon Sep 17 00:00:00 2001 From: zrj Date: Tue, 9 Apr 2019 11:39:05 +0300 Subject: [PATCH] libc/stdlib: Add recallocarray() function. It is useful function for security related features, like resizing memory objects containing sensitive data to avoid information leaking. Update manpage. Taken-from: OpenBSD --- include/stdlib.h | 2 + lib/libc/stdlib/Makefile.inc | 3 +- lib/libc/stdlib/Symbol.map | 1 + lib/libc/stdlib/reallocarray.3 | 30 ++++++++++--- lib/libc/stdlib/recallocarray.c | 80 +++++++++++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 lib/libc/stdlib/recallocarray.c diff --git a/include/stdlib.h b/include/stdlib.h index fa4579b476..f983f0ff67 100644 --- a/include/stdlib.h +++ b/include/stdlib.h @@ -301,6 +301,8 @@ void qsort_r(void *, size_t, size_t, void *, int radixsort(const unsigned char **, int, const unsigned char *, unsigned int); void *reallocarray(void *, size_t, size_t) __heedresult __alloc_size2(2, 3); +void *recallocarray(void *, size_t, size_t, size_t) __heedresult + __alloc_size2(3, 4); void *reallocf(void *, size_t) __heedresult __alloc_size(2); int rpmatch(const char *); void setprogname(const char *); diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc index 0d6c8661ac..d47dd3be17 100644 --- a/lib/libc/stdlib/Makefile.inc +++ b/lib/libc/stdlib/Makefile.inc @@ -15,7 +15,7 @@ MISRCS+=a64l.c abort.c abs.c atexit.c \ insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \ merge.c ptsname.c qsort.c qsort_r.c quick_exit.c \ radixsort.c rand.c random.c \ - reallocarray.c reallocf.c realpath.c remque.c \ + reallocarray.c reallocf.c realpath.c recallocarray.c remque.c \ strfmon.c strsuftoll.c strtoimax.c \ strtol.c strtoll.c strtonum.c strtoq.c strtoul.c strtoull.c \ strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c @@ -75,6 +75,7 @@ MLINKS+=qsort.3 heapsort.3 \ qsort.3 mergesort.3 \ qsort.3 qsort_r.3 MLINKS+=radixsort.3 sradixsort.3 +MLINKS+=reallocarray.3 recallocarray.3 MLINKS+=rand.3 rand_r.3 \ rand.3 srand.3 \ rand.3 sranddev.3 diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map index 7c64fef763..c064e320e4 100644 --- a/lib/libc/stdlib/Symbol.map +++ b/lib/libc/stdlib/Symbol.map @@ -121,6 +121,7 @@ DF506.0 { __cxa_thread_atexit_impl; freezero; reallocarray; + recallocarray; }; /* diff --git a/lib/libc/stdlib/reallocarray.3 b/lib/libc/stdlib/reallocarray.3 index dbf16d9636..3bd01869d3 100644 --- a/lib/libc/stdlib/reallocarray.3 +++ b/lib/libc/stdlib/reallocarray.3 @@ -28,25 +28,27 @@ .\" .\" $FreeBSD: head/lib/libc/stdlib/reallocarray.3 282472 2015-05-05 10:44:17Z pluknet $ .\" -.Dd January 12, 2019 +.Dd April 11, 2019 .Dt REALLOCARRAY 3 .Os .Sh NAME -.Nm reallocarray -.Nd memory reallocation function +.Nm reallocarray , +.Nm recallocarray +.Nd memory reallocation functions .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In stdlib.h .Ft void * .Fn reallocarray "void *ptr" "size_t number" "size_t size" +.Ft void * +.Fn recallocarray "void *ptr" "size_t oldnmemb" "size_t nmemb" "size_t size" .Sh DESCRIPTION The .Fn reallocarray function is similar to the .Fn realloc -function -except it operates on +function except it operates on .Fa number members of size .Fa size @@ -54,6 +56,13 @@ and checks for integer overflow in the calculation .Fa number * .Fa size . +.Pp +The +.Fn recallocarray +function is similar to +.Fn reallocarray +except it ensures newly allocated memory is cleared similar to +.Fn calloc . .Sh RETURN VALUES The .Fn reallocarray @@ -137,6 +146,13 @@ if ((newp = reallocarray(p, num, size)) == NULL) { The .Fn reallocarray function first appeared in -.Ox 5.6 +.Ox +/ +.Dx 5.6 . +.Pp +The +.Fn recallocarray +function appeared in +.Ox 6.1 and -.Fx 11.0 . +.Dx 5.6 . diff --git a/lib/libc/stdlib/recallocarray.c b/lib/libc/stdlib/recallocarray.c new file mode 100644 index 0000000000..84d736bf96 --- /dev/null +++ b/lib/libc/stdlib/recallocarray.c @@ -0,0 +1,80 @@ +/* $OpenBSD: recallocarray.c,v 1.1 2017/03/06 18:44:21 otto Exp $ */ +/* + * Copyright (c) 2008, 2017 Otto Moerbeek + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include +#include +#include +#include + +/* + * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX + * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW + */ +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4)) + +void * +recallocarray(void *ptr, size_t oldnmemb, size_t newnmemb, size_t size) +{ + size_t oldsize, newsize; + void *newptr; + + if (ptr == NULL) + return calloc(newnmemb, size); + + if ((newnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + newnmemb > 0 && SIZE_MAX / newnmemb < size) { + errno = ENOMEM; + return NULL; + } + newsize = newnmemb * size; + + if ((oldnmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + oldnmemb > 0 && SIZE_MAX / oldnmemb < size) { + errno = EINVAL; + return NULL; + } + oldsize = oldnmemb * size; + + /* + * Don't bother too much if we're shrinking just a bit, + * we do not shrink for series of small steps, oh well. + */ + if (newsize <= oldsize) { + size_t d = oldsize - newsize; + + if (d < oldsize / 2 && d < (size_t)getpagesize()) { + memset((char *)ptr + newsize, 0, d); + return ptr; + } + } + + newptr = malloc(newsize); + if (newptr == NULL) + return NULL; + + if (newsize > oldsize) { + memcpy(newptr, ptr, oldsize); + memset((char *)newptr + oldsize, 0, newsize - oldsize); + } else + memcpy(newptr, ptr, newsize); + + explicit_bzero(ptr, oldsize); + free(ptr); + + return newptr; +} -- 2.41.0