mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-03 19:08:58 +00:00
MFC r327674, r327796
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. Additionally, move the overflow check logic out to WOULD_OVERFLOW() for consumers to have a common means of testing for overflowing allocations. WOULD_OVERFLOW() should be a secondary check -- on 64-bit platforms, just because an allocation won't overflow size_t does not mean it is a sane size to request. Callers should be imposing reasonable allocation limits far, far, below overflow. Obtained from: OpenBSD
This commit is contained in:
parent
877996fe6d
commit
2506e2e267
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/stable/10/; revision=328276
@ -29,7 +29,7 @@
|
||||
.\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 15, 2012
|
||||
.Dd January 10, 2018
|
||||
.Dt MALLOC 9
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -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
|
||||
@ -144,6 +154,7 @@ If the request cannot be immediately fulfilled, the current process is put
|
||||
to sleep to wait for resources to be released by other processes.
|
||||
The
|
||||
.Fn malloc ,
|
||||
.Fn mallocarray ,
|
||||
.Fn realloc ,
|
||||
and
|
||||
.Fn reallocf
|
||||
@ -152,6 +163,13 @@ functions cannot return
|
||||
if
|
||||
.Dv M_WAITOK
|
||||
is specified.
|
||||
if the multiplication of
|
||||
.Fa nmemb
|
||||
and
|
||||
.Fa size
|
||||
would cause an integer overflow, the
|
||||
.Fn mallocarray
|
||||
function induces a panic.
|
||||
.It Dv M_USE_RESERVE
|
||||
Indicates that the system can use its reserve of memory to satisfy the
|
||||
request.
|
||||
|
@ -2,6 +2,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
|
||||
@ -529,6 +530,16 @@ malloc(unsigned long size, struct malloc_type *mtp, int flags)
|
||||
return ((void *) va);
|
||||
}
|
||||
|
||||
void *
|
||||
mallocarray(size_t nmemb, size_t size, struct malloc_type *type, int flags)
|
||||
{
|
||||
|
||||
if (WOULD_OVERFLOW(nmemb, size))
|
||||
panic("mallocarray: %zu * %zu overflowed", nmemb, size);
|
||||
|
||||
return (malloc(size * nmemb, type, flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* free:
|
||||
*
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <sys/queue.h>
|
||||
#include <sys/_lock.h>
|
||||
#include <sys/_mutex.h>
|
||||
#include <machine/_limits.h>
|
||||
|
||||
#define MINALLOCSIZE UMA_SMALLEST_UNIT
|
||||
|
||||
@ -176,6 +177,8 @@ void *contigmalloc(unsigned long size, struct malloc_type *type, int flags,
|
||||
vm_paddr_t boundary) __malloc_like;
|
||||
void free(void *addr, struct malloc_type *type);
|
||||
void *malloc(unsigned long size, struct malloc_type *type, int flags) __malloc_like;
|
||||
void *mallocarray(size_t nmemb, size_t size, struct malloc_type *type,
|
||||
int flags) __malloc_like __result_use_check;
|
||||
void malloc_init(void *);
|
||||
int malloc_last_fail(void);
|
||||
void malloc_type_allocated(struct malloc_type *type, unsigned long size);
|
||||
@ -188,6 +191,20 @@ void *reallocf(void *addr, unsigned long size, struct malloc_type *type,
|
||||
int flags);
|
||||
|
||||
struct malloc_type *malloc_desc2type(const char *desc);
|
||||
|
||||
/*
|
||||
* 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))
|
||||
static inline bool
|
||||
WOULD_OVERFLOW(size_t nmemb, size_t size)
|
||||
{
|
||||
|
||||
return ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
|
||||
nmemb > 0 && __SIZE_T_MAX / nmemb < size);
|
||||
}
|
||||
#undef MUL_NO_OVERFLOW
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* !_SYS_MALLOC_H_ */
|
||||
|
Loading…
Reference in New Issue
Block a user