Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 20 Jan 2018 23:46:04 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r328210 - in stable/11: share/man/man9 sys/kern sys/sys
Message-ID:  <201801202346.w0KNk4at083285@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Sat Jan 20 23:46:03 2018
New Revision: 328210
URL: https://svnweb.freebsd.org/changeset/base/328210

Log:
  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

Modified:
  stable/11/share/man/man9/malloc.9
  stable/11/sys/kern/kern_malloc.c
  stable/11/sys/sys/malloc.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/share/man/man9/malloc.9
==============================================================================
--- stable/11/share/man/man9/malloc.9	Sat Jan 20 22:24:45 2018	(r328209)
+++ stable/11/share/man/man9/malloc.9	Sat Jan 20 23:46:03 2018	(r328210)
@@ -29,7 +29,7 @@
 .\" $NetBSD: malloc.9,v 1.3 1996/11/11 00:05:11 lukem Exp $
 .\" $FreeBSD$
 .\"
-.Dd November 19, 2015
+.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 cu
 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.

Modified: stable/11/sys/kern/kern_malloc.c
==============================================================================
--- stable/11/sys/kern/kern_malloc.c	Sat Jan 20 22:24:45 2018	(r328209)
+++ stable/11/sys/kern/kern_malloc.c	Sat Jan 20 23:46:03 2018	(r328210)
@@ -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
@@ -524,6 +525,16 @@ malloc(unsigned long size, struct malloc_type *mtp, in
 		va = redzone_setup(va, osize);
 #endif
 	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));
 }
 
 /*

Modified: stable/11/sys/sys/malloc.h
==============================================================================
--- stable/11/sys/sys/malloc.h	Sat Jan 20 22:24:45 2018	(r328209)
+++ stable/11/sys/sys/malloc.h	Sat Jan 20 23:46:03 2018	(r328210)
@@ -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
 
@@ -175,6 +176,9 @@ void	*contigmalloc(unsigned long size, struct malloc_t
 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);
@@ -187,6 +191,20 @@ void	*reallocf(void *addr, unsigned long size, struct 
 	    int flags) __result_use_check __alloc_size(2);
 
 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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201801202346.w0KNk4at083285>