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:
Kristof Provost 2018-01-07 13:21:01 +00:00
parent 6d5343e38e
commit fd91e076c1
3 changed files with 39 additions and 0 deletions

View File

@ -45,6 +45,8 @@
.In sys/malloc.h .In sys/malloc.h
.Ft void * .Ft void *
.Fn malloc "unsigned long size" "struct malloc_type *type" "int flags" .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 .Ft void
.Fn free "void *addr" "struct malloc_type *type" .Fn free "void *addr" "struct malloc_type *type"
.Ft void * .Ft void *
@ -64,6 +66,14 @@ object whose size is specified by
.Fa size . .Fa size .
.Pp .Pp
The 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 .Fn free
function releases memory at address function releases memory at address
.Fa addr .Fa addr
@ -152,6 +162,15 @@ functions cannot return
if if
.Dv M_WAITOK .Dv M_WAITOK
is specified. 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 .It Dv M_USE_RESERVE
Indicates that the system can use its reserve of memory to satisfy the Indicates that the system can use its reserve of memory to satisfy the
request. request.

View File

@ -4,6 +4,7 @@
* Copyright (c) 1987, 1991, 1993 * Copyright (c) 1987, 1991, 1993
* The Regents of the University of California. * The Regents of the University of California.
* Copyright (c) 2005-2009 Robert N. M. Watson * Copyright (c) 2005-2009 Robert N. M. Watson
* Copyright (c) 2008 Otto Moerbeek <otto@drijf.net> (mallocarray)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * 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); 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: * 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 free(void *addr, struct malloc_type *type);
void *malloc(unsigned long size, struct malloc_type *type, int flags) void *malloc(unsigned long size, struct malloc_type *type, int flags)
__malloc_like __result_use_check __alloc_size(1); __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 *); void malloc_init(void *);
int malloc_last_fail(void); int malloc_last_fail(void);
void malloc_type_allocated(struct malloc_type *type, unsigned long size); void malloc_type_allocated(struct malloc_type *type, unsigned long size);