Introduce mallocarray() in the kernel

Similar to calloc() the mallocarray() function checks for integer
overflows before allocating memory.
It does not zero memory, unless the M_ZERO flag is set.

Reviewed by:	pfg, vangyzen (previous version), imp (previous version)
Obtained from:	OpenBSD
Differential Revision:	https://reviews.freebsd.org/D13766
This commit is contained in:
kp 2018-01-07 13:21:01 +00:00
parent d85f21b483
commit 69291826ac
3 changed files with 39 additions and 0 deletions

View File

@ -45,6 +45,8 @@
.In sys/malloc.h
.Ft void *
.Fn malloc "unsigned long size" "struct malloc_type *type" "int flags"
.Ft void *
.Fn mallocarray "size_t nmemb" "size_t size" "struct malloc_type *type" "int flags"
.Ft void
.Fn free "void *addr" "struct malloc_type *type"
.Ft void *
@ -64,6 +66,14 @@ object whose size is specified by
.Fa size .
.Pp
The
.Fn mallocarray
function allocates uninitialized memory in kernel address space for an
array of
.Fa nmemb
entries whose size is specified by
.Fa size .
.Pp
The
.Fn free
function releases memory at address
.Fa addr
@ -152,6 +162,15 @@ functions cannot return
if
.Dv M_WAITOK
is specified.
The
.Fn mallocarray
function can return
.Dv NULL
if the multiplication of
.Fa nmemb
and
.Fa size
would cause an integer overflow.
.It Dv M_USE_RESERVE
Indicates that the system can use its reserve of memory to satisfy the
request.

View File

@ -4,6 +4,7 @@
* Copyright (c) 1987, 1991, 1993
* The Regents of the University of California.
* Copyright (c) 2005-2009 Robert N. M. Watson
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> (mallocarray)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -534,6 +535,22 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags)
return ((void *) va);
}
/*
* 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 (1UL << (sizeof(size_t) * 8 / 2))
void *
mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags)
{
if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
nmemb > 0 && SIZE_MAX / nmemb < size)
return (NULL);
return (malloc(size * nmemb, type, flags));
}
/*
* free:
*

View File

@ -177,6 +177,9 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags,
void free(void *addr, struct malloc_type *type);
void *malloc(unsigned long size, struct malloc_type *type, int flags)
__malloc_like __result_use_check __alloc_size(1);
void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type,
int flags) __malloc_like __result_use_check
__alloc_size(1) __alloc_size(2);
void malloc_init(void *);
int malloc_last_fail(void);
void malloc_type_allocated(struct malloc_type *type, unsigned long size);