On Thu, Jul 10, 2014 at 02:42:34PM -0400, Ted Unangst wrote: > On Thu, Jul 10, 2014 at 10:28, Matthew Dempsky wrote: > > We've found a bunch of uses for reallocarray() in userland, and I > > think the idiom is worth reusing in the kernel. There are enough > > places where we do malloc(x * y) that I think it makes sense to add > > mallocarray(x, y). > > > +void *malloc(unsigned long size, int type, int flags); > > +void *mallocarray(unsigned long nmemb, unsigned long size, > > + int type, int flags); > > The unsigned long here is ancient history. It should be size_t I think. > > > Index: sys/kern/kern_mallocarray.c > > Please just add it to kern_malloc.c without creating a new file.
ok? Index: share/man/man9/Makefile =================================================================== RCS file: /home/matthew/cvs-mirror/cvs/src/share/man/man9/Makefile,v retrieving revision 1.210 diff -u -p -r1.210 Makefile --- share/man/man9/Makefile 30 Jun 2014 21:48:09 -0000 1.210 +++ share/man/man9/Makefile 10 Jul 2014 17:15:45 -0000 @@ -232,7 +232,7 @@ MLINKS+=ktrace.9 ktrcsw.9 ktrace.9 ktrem ktrace.9 ktrsysret.9 ktrace.9 KTRPOINT.9 MLINKS+=lock.9 lockinit.9 lock.9 lockmgr.9 lock.9 lockstatus.9 MLINKS+=log.9 addlog.9 -MLINKS+=malloc.9 free.9 +MLINKS+=malloc.9 mallocarray.9 malloc.9 free.9 MLINKS+=membar_sync.9 membar_enter.9 membar_sync.9 membar_exit.9 \ membar_sync.9 membar_producer.9 membar_sync.9 membar_consumer.9 MLINKS+=mbuf.9 m_copym2.9 mbuf.9 m_copym.9 mbuf.9 m_free.9 mbuf.9 MFREE.9 \ Index: share/man/man9/malloc.9 =================================================================== RCS file: /home/matthew/cvs-mirror/cvs/src/share/man/man9/malloc.9,v retrieving revision 1.52 diff -u -p -r1.52 malloc.9 --- share/man/man9/malloc.9 3 Apr 2014 04:10:34 -0000 1.52 +++ share/man/man9/malloc.9 10 Jul 2014 18:52:54 -0000 @@ -33,13 +33,16 @@ .Os .Sh NAME .Nm malloc , +.Nm mallocarray , .Nm free .Nd kernel memory allocator .Sh SYNOPSIS .In sys/types.h .In sys/malloc.h .Ft void * -.Fn malloc "unsigned long size" "int type" "int flags" +.Fn malloc "size_t size" "int type" "int flags" +.Ft void * +.Fn malloc "size_t nmemb" "size_t size" "int type" "int flags" .Ft void .Fn free "void *addr" "int type" .Sh DESCRIPTION @@ -48,8 +51,17 @@ The function allocates uninitialized memory in kernel address space for an object whose size is specified by .Fa size . +The +.Fn mallocarray +function is the same as +.Fn malloc , +except it allocates space for an array of +.Fa nmemb +objects and checks for arithmetic overflow. +.Pp +The .Fn free -releases memory at address +function releases memory at address .Fa addr that was previously allocated by .Fn malloc @@ -60,7 +72,8 @@ is a null pointer, no action occurs. .Pp The .Fa flags -argument further qualifies malloc's +argument further qualifies +.Fn malloc Ns 's operational characteristics as follows: .Bl -tag -width xxx -offset indent .It Dv M_WAITOK Index: sys/sys/malloc.h =================================================================== RCS file: /home/matthew/cvs-mirror/cvs/src/sys/sys/malloc.h,v retrieving revision 1.108 diff -u -p -r1.108 malloc.h --- sys/sys/malloc.h 19 May 2014 14:30:03 -0000 1.108 +++ sys/sys/malloc.h 10 Jul 2014 18:49:44 -0000 @@ -391,10 +391,11 @@ extern struct kmemusage *kmemusage; extern char *kmembase; extern struct kmembuckets bucket[]; -extern void *malloc(unsigned long size, int type, int flags); -extern void free(void *addr, int type); -extern int sysctl_malloc(int *, u_int, void *, size_t *, void *, size_t, - struct proc *); +void *malloc(size_t, int, int); +void *mallocarray(size_t, size_t, int, int); +void free(void *, int); +int sysctl_malloc(int *, u_int, void *, size_t *, void *, size_t, + struct proc *); size_t malloc_roundup(size_t); void malloc_printit(int (*)(const char *, ...)); Index: sys/kern/kern_malloc.c =================================================================== RCS file: /home/matthew/cvs-mirror/cvs/src/sys/kern/kern_malloc.c,v retrieving revision 1.107 diff -u -p -r1.107 kern_malloc.c --- sys/kern/kern_malloc.c 19 May 2014 14:30:03 -0000 1.107 +++ sys/kern/kern_malloc.c 10 Jul 2014 18:50:15 -0000 @@ -159,7 +159,7 @@ struct timeval malloc_lasterr; * Allocate a block of memory */ void * -malloc(unsigned long size, int type, int flags) +malloc(size_t size, int type, int flags) { struct kmembuckets *kbp; struct kmemusage *kup; @@ -701,3 +701,37 @@ malloc_printit( #endif } #endif /* DDB */ + +/* + * Copyright (c) 2008 Otto Moerbeek <o...@drijf.net> + * + * 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. + */ + +/* + * 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) * 4)) + +void * +mallocarray(size_t nmemb, size_t size, int type, int flags) +{ + if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && + nmemb > 0 && SIZE_MAX / nmemb < size) { + if (flags & M_CANFAIL) + return (NULL); + panic("overflow"); + } + return (malloc(size * nmemb, type, flags)); +}