summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordoug <>2014-10-19 17:58:14 +0000
committerdoug <>2014-10-19 17:58:14 +0000
commit4df28d31f8d900d5d1d164c0c75e270e82e11e81 (patch)
treea4649fb344da28a3c612e514e4c96cbb473efdeb /src
parent166117897f0e1f5aef7866f9e8eb9672a27313ab (diff)
downloadopenbsd-4df28d31f8d900d5d1d164c0c75e270e82e11e81.tar.gz
openbsd-4df28d31f8d900d5d1d164c0c75e270e82e11e81.tar.bz2
openbsd-4df28d31f8d900d5d1d164c0c75e270e82e11e81.zip
Revamp malloc.3 by reordering the sections and rewriting parts.
The old man page had a lot of useful information, but it was all mixed together which made it difficult to reference. The main theme in this commit is that the sections are more focused: * DESCRIPTION describes the overall behavior * RETURN VALUES describes what it may return (including implementation defined values) * EXAMPLES shows why we recently started an audit on malloc and realloc usage in the tree. * Added CAVEATS which describes what is implementation defined, gotchas and security implications of misusing these functions * Added IDIOMS which describes how these functions should or should not be used The MALLOC_OPTIONS section was left unchanged. Function names were added to DIAGNOSTICS and STANDARDS. The MALLOC_OPTIONS and DIAGNOSTICS sections were pushed down in the page so more pertinent information is higher up. This has gone through several revisions thanks to input from deraadt@ and schwarze@. Ingo also helped with some of the mandoc formatting. OK schwarze@ (as far as it is a good starting point and the code snippets look ok)
Diffstat (limited to 'src')
-rw-r--r--src/lib/libc/stdlib/malloc.3602
1 files changed, 417 insertions, 185 deletions
diff --git a/src/lib/libc/stdlib/malloc.3 b/src/lib/libc/stdlib/malloc.3
index d738524c81..4185648c84 100644
--- a/src/lib/libc/stdlib/malloc.3
+++ b/src/lib/libc/stdlib/malloc.3
@@ -30,9 +30,9 @@
30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31.\" SUCH DAMAGE. 31.\" SUCH DAMAGE.
32.\" 32.\"
33.\" $OpenBSD: malloc.3,v 1.78 2014/05/01 18:41:59 jmc Exp $ 33.\" $OpenBSD: malloc.3,v 1.79 2014/10/19 17:58:14 doug Exp $
34.\" 34.\"
35.Dd $Mdocdate: May 1 2014 $ 35.Dd $Mdocdate: October 19 2014 $
36.Dt MALLOC 3 36.Dt MALLOC 3
37.Os 37.Os
38.Sh NAME 38.Sh NAME
@@ -65,58 +65,15 @@ The
65function allocates uninitialized space for an object whose 65function allocates uninitialized space for an object whose
66size is specified by 66size is specified by
67.Fa size . 67.Fa size .
68The
69.Fn malloc 68.Fn malloc
70function maintains multiple lists of free blocks according to size, allocating 69maintains multiple lists of free blocks according to size, allocating
71space from the appropriate list. 70space from the appropriate list.
72.Pp 71The allocated space is suitably aligned (after possible pointer coercion) for
73The allocated space is 72storage of any type of object.
74suitably aligned (after possible pointer
75coercion) for storage of any type of object.
76If the space is of 73If the space is of
77.Em pagesize 74.Em pagesize
78or larger, the memory returned will be page-aligned. 75or larger, the memory returned will be page-aligned.
79.Pp 76.Pp
80Allocation of a zero size object returns a pointer to a zero size object.
81This zero size object is access protected, so any access to it will
82generate an exception (SIGSEGV).
83Many zero-sized objects can be placed consecutively in shared
84protected pages.
85The minimum size of the protection on each object is suitably aligned and
86sized as previously stated, but the protection may extend further depending
87on where in a protected zone the object lands.
88.Pp
89When using
90.Fn malloc
91be careful to avoid the following idiom:
92.Bd -literal -offset indent
93if ((p = malloc(num * size)) == NULL)
94 err(1, "malloc");
95.Ed
96.Pp
97The multiplication may lead to an integer overflow, which can
98be avoided using the extension
99.Fn reallocarray ,
100as follows:
101.Bd -literal -offset indent
102if ((p = reallocarray(NULL, num, size)) == NULL)
103 err(1, "malloc");
104.Ed
105.Pp
106Alternatively
107.Fn calloc
108is a more portable solution which comes with the cost of clearing memory.
109.Pp
110If
111.Fn malloc
112must be used, be sure to test for overflow:
113.Bd -literal -offset indent
114if (size && num > SIZE_MAX / size) {
115 errno = ENOMEM;
116 err(1, "overflow");
117}
118.Ed
119.Pp
120The 77The
121.Fn calloc 78.Fn calloc
122function allocates space for an array of 79function allocates space for an array of
@@ -124,12 +81,35 @@ function allocates space for an array of
124objects, each of whose size is 81objects, each of whose size is
125.Fa size . 82.Fa size .
126The space is initialized to zero. 83The space is initialized to zero.
127The use of 84.Pp
85The
86.Fn realloc
87function changes the size of the object pointed to by
88.Fa ptr
89to
90.Fa size
91bytes and returns a pointer to the (possibly moved) object.
92The contents of the object are unchanged up to the lesser
93of the new and old sizes.
94If the new size is larger, the value of the newly allocated portion
95of the object is indeterminate and uninitialized.
96If the space cannot be allocated, the object
97pointed to by
98.Fa ptr
99is unchanged.
100.Pp
101The
128.Fn reallocarray 102.Fn reallocarray
129or 103function is similar to
130.Fn calloc 104.Fn realloc
131is strongly encouraged when allocating multiple sized objects 105except it operates on
132in order to avoid possible integer overflows. 106.Fa nmemb
107members of size
108.Fa size
109and checks for integer overflow in
110.Fa nmemb
111*
112.Fa size .
133.Pp 113.Pp
134The 114The
135.Fn free 115.Fn free
@@ -140,7 +120,17 @@ allocation or, if required, to be returned to the kernel using
140.Xr munmap 2 . 120.Xr munmap 2 .
141If 121If
142.Fa ptr 122.Fa ptr
143is a null pointer, no action occurs. 123is a
124.Dv NULL
125pointer, no action occurs.
126If
127.Fa ptr
128was previously freed by
129.Fn free
130.Fn realloc ,
131or
132.Fn reallocarray ,
133the behavior is undefined and the double free is a security concern.
144.Pp 134.Pp
145A 135A
146.Fn cfree 136.Fn cfree
@@ -148,38 +138,135 @@ function is also provided for compatibility with old systems and other
148.Nm malloc 138.Nm malloc
149libraries; it is simply an alias for 139libraries; it is simply an alias for
150.Fn free . 140.Fn free .
141.Sh RETURN VALUES
142If
143.Fn malloc ,
144.Fn calloc ,
145.Fn realloc ,
146or
147.Fn reallocarray
148is called with
149.Fa size
150or
151.Fa nmemb
152is equal to 0,
153a pointer to an access protected, zero sized object is returned.
154.Pp
155If
156.Fn malloc
157is called with
158.Fa size
159greater than 0, it returns a pointer to the allocated space if successful;
160otherwise, a
161.Dv NULL
162pointer is returned and
163.Va errno
164is set to
165.Er ENOMEM .
151.Pp 166.Pp
152The 167The
153.Fn realloc 168.Fn calloc
154function changes the size of the object pointed to by 169function checks for integer overflow and returns
155.Fa ptr 170.Dv NULL
156to 171if
172.Fa nmemb
173*
157.Fa size 174.Fa size
158bytes and returns a pointer to the (possibly moved) object. 175will result in integer overflow.
159The contents of the object are unchanged up to the lesser
160of the new and old sizes.
161If the new size is larger, the value of the newly allocated portion
162of the object is indeterminate and uninitialized.
163If 176If
164.Fa ptr 177.Fa nmemb
165is a null pointer, the 178and
179.Fa size
180are greater than 0,
181.Fn calloc
182returns a pointer to the allocated space if successful; otherwise, a
183.Dv NULL
184pointer is returned and
185.Va errno
186is set to
187.Er ENOMEM .
188.Pp
189The
166.Fn realloc 190.Fn realloc
167function behaves like the 191function behaves like
168.Fn malloc 192.Fn malloc
169function for the specified size. 193for the specified
170If the space cannot be allocated, the object 194.Fa size
171pointed to by 195when
172.Fa ptr 196.Fa ptr
173is unchanged. 197is
198.Dv NULL .
174If 199If
175.Fa size 200.Fa size
176is zero and 201is greater than 0,
177.Fa ptr 202.Fn realloc
178is not a null pointer, the object it points to is freed and a new zero size 203returns a pointer to the allocated space if successful; otherwise, a
179object is returned. 204.Dv NULL
205pointer is returned and
206.Va errno
207is set to
208.Er ENOMEM .
209.Pp
210The
211.Fn reallocarray
212function checks for integer overflow and returns
213.Dv NULL
214if
215.Fa nmemb
216*
217.Fa size
218will result in integer overflow.
219If
220.Fn reallocarray
221is called with
222.Fa size
223and
224.Fa nmemb
225greater than 0, it returns a pointer to the allocated space if successful;
226otherwise, a
227.Dv NULL
228pointer is returned and
229.Va errno
230is set to
231.Er ENOMEM .
232.Pp
233The
234.Fn free
235and
236.Fn cfree
237functions return no value.
238.Sh IDIOMS
239Consider
240.Fn calloc
241or the extension
242.Fn reallocarray
243when you have multiplication in the
244.Fa size
245argument of
246.Fn malloc
247or
248.Fn realloc .
249For example, avoid this common idiom as it may lead to integer overflow:
250.Bd -literal -offset indent
251if ((p = malloc(num * size)) == NULL)
252 err(1, "malloc");
253.Ed
254.Pp
255A drop-in replacement is the
256.Ox
257extension
258.Fn reallocarray :
259.Bd -literal -offset indent
260if ((p = reallocarray(NULL, num, size)) == NULL)
261 err(1, "reallocarray");
262.Ed
263.Pp
264Alternatively,
265.Fn calloc
266may be used at the cost of initialization overhead.
180.Pp 267.Pp
181When using 268When using
182.Fn realloc 269.Fn realloc ,
183be careful to avoid the following idiom: 270be careful to avoid the following idiom:
184.Bd -literal -offset indent 271.Bd -literal -offset indent
185size += 50; 272size += 50;
@@ -208,13 +295,187 @@ size = newsize;
208.Ed 295.Ed
209.Pp 296.Pp
210As with 297As with
211.Fn malloc 298.Fn malloc ,
212it is important to ensure the new size value will not overflow; 299it is important to ensure the new size value will not overflow;
213i.e. avoid allocations like the following: 300i.e. avoid allocations like the following:
214.Bd -literal -offset indent 301.Bd -literal -offset indent
215if ((newp = realloc(p, num * size)) == NULL) { 302if ((newp = realloc(p, num * size)) == NULL) {
216 ... 303 ...
217.Ed 304.Ed
305.Pp
306Instead, use
307.Fn reallocarray :
308.Bd -literal -offset indent
309if ((newp = reallocarray(p, num, size)) == NULL) {
310 ...
311.Ed
312.Pp
313Code designed for some ancient platforms avoided calling
314.Fn realloc
315with a
316.Dv NULL
317.Fa ptr .
318Such hacks are no longer necessary in modern code. Instead of
319this idiom:
320.Bd -literal -offset indent
321if (p == NULL)
322 newp = malloc(newsize);
323else
324 newp = realloc(p, newsize);
325.Ed
326.Pp
327Use the following as calling
328.Fn realloc
329with
330.Dv NULL
331is equivalent to calling
332.Fn malloc :
333.Bd -literal -offset indent
334newp = realloc(p, newsize);
335.Ed
336.Sh ENVIRONMENT
337.Bl -tag -width Ev
338.It Ev MALLOC_OPTIONS
339See below.
340.El
341.Sh FILES
342.Bl -tag -width "/etc/malloc.conf"
343.It Pa /etc/malloc.conf
344symbolic link to filename containing option flags
345.El
346.Sh EXAMPLES
347If
348.Fn malloc
349must be used with multiplication, be sure to test for overflow:
350.Bd -literal -offset indent
351size_t size;
352size_t num;
353\&...
354
355/* Check for size_t overflow */
356if (size && num > SIZE_MAX / size) {
357 errno = EOVERFLOW;
358 err(1, "overflow");
359}
360if ((p = malloc(size * num)) == NULL)
361 err(1, "malloc");
362.Ed
363.Pp
364The above test is not sufficient in all cases. For example, multiplying
365ints requires a different set of checks:
366.Bd -literal -offset indent
367int size;
368int num;
369\&...
370
371/* Avoid invalid requests */
372if (size < 0 || num < 0) {
373 errno = EOVERFLOW;
374 err(1, "overflow");
375}
376
377/* Check for signed int overflow */
378if (size && num > INT_MAX / size) {
379 errno = EOVERFLOW;
380 err(1, "overflow");
381}
382
383if ((p = malloc(size * num)) == NULL)
384 err(1, "malloc");
385.Ed
386.Pp
387Assuming the implementation checks for integer overflow as
388.Ox
389does, it is much easier to use
390.Fn calloc
391or
392.Fn reallocarray .
393.Pp
394The above examples could be simplified to:
395.Bd -literal -offset indent
396if ((p = reallocarray(NULL, num, size)) == NULL)
397 err(1, "reallocarray");
398.Ed
399.Pp
400or at the cost of initialization:
401.Bd -literal -offset indent
402if ((p = calloc(num, size)) == NULL)
403 err(1, "calloc");
404.Ed
405.Sh DIAGNOSTICS
406If
407.Fn malloc ,
408.Fn calloc ,
409.Fn realloc ,
410.Fn reallocarray ,
411or
412.Fn free
413detect an error condition,
414a message will be printed to file descriptor
4152 (not using stdio).
416Errors will result in the process being aborted,
417unless the
418.Cm a
419option has been specified.
420.Pp
421Here is a brief description of the error messages and what they mean:
422.Bl -tag -width Ds
423.It Dq out of memory
424If the
425.Cm X
426option is specified it is an error for
427.Fn malloc ,
428.Fn calloc ,
429.Fn realloc ,
430or
431.Fn reallocarray
432to return
433.Dv NULL .
434.It Dq malloc init mmap failed
435This is a rather weird condition that is most likely to indicate a
436seriously overloaded system or a ulimit restriction.
437.It Dq bogus pointer (double free?)
438An attempt to
439.Fn free ,
440.Fn realloc ,
441or
442.Fn reallocarray
443an unallocated pointer was made.
444.It Dq chunk is already free
445There was an attempt to free a chunk that had already been freed.
446.It Dq modified chunk-pointer
447The pointer passed to
448.Fn free ,
449.Fn realloc ,
450or
451.Fn reallocarray
452has been modified.
453.It Dq recursive call
454An attempt was made to call recursively into these functions, i.e., from a
455signal handler.
456This behavior is not supported.
457In particular, signal handlers should
458.Em not
459use any of the
460.Fn malloc
461functions nor utilize any other functions which may call
462.Fn malloc
463(e.g.,
464.Xr stdio 3
465routines).
466.It Dq unknown char in MALLOC_OPTIONS
467We found something we didn't understand.
468.It Dq malloc cache overflow/underflow
469The internal malloc page cache has been corrupted.
470.It Dq malloc free slot lost
471The internal malloc page cache has been corrupted.
472.It Dq guard size
473An inconsistent guard size was detected.
474.It any other error
475.Fn malloc
476detected an internal error;
477consult sources and/or wizards.
478.El
218.Sh MALLOC_OPTIONS 479.Sh MALLOC_OPTIONS
219Malloc will first look for a symbolic link called 480Malloc will first look for a symbolic link called
220.Pa /etc/malloc.conf 481.Pa /etc/malloc.conf
@@ -335,122 +596,22 @@ are used,
335it is buggy. 596it is buggy.
336.Pp 597.Pp
337The default number of free pages cached is 64. 598The default number of free pages cached is 64.
338.Sh RETURN VALUES
339The
340.Fn malloc ,
341.Fn reallocarray ,
342and
343.Fn calloc
344functions return a pointer to the allocated space if successful; otherwise,
345a null pointer is returned and
346.Va errno
347is set to
348.Er ENOMEM .
349.Pp
350The
351.Fn free
352and
353.Fn cfree
354functions return no value.
355.Pp
356The
357.Fn realloc
358function returns a pointer to the (possibly moved) allocated space
359if successful; otherwise, a null pointer is returned and
360.Va errno
361is set to
362.Er ENOMEM .
363.Sh ENVIRONMENT
364.Bl -tag -width Ev
365.It Ev MALLOC_OPTIONS
366See above.
367.El
368.Sh FILES
369.Bl -tag -width "/etc/malloc.conf"
370.It Pa /etc/malloc.conf
371symbolic link to filename containing option flags
372.El
373.Sh DIAGNOSTICS
374If
375.Fn malloc ,
376.Fn calloc ,
377.Fn realloc ,
378or
379.Fn free
380detect an error condition,
381a message will be printed to file descriptor
3822 (not using stdio).
383Errors will result in the process being aborted,
384unless the
385.Cm a
386option has been specified.
387.Pp
388Here is a brief description of the error messages and what they mean:
389.Bl -tag -width Ds
390.It Dq out of memory
391If the
392.Cm X
393option is specified it is an error for
394.Fn malloc ,
395.Fn calloc ,
396or
397.Fn realloc
398to return
399.Dv NULL .
400.It Dq malloc init mmap failed
401This is a rather weird condition that is most likely to indicate a
402seriously overloaded system or a ulimit restriction.
403.It Dq bogus pointer (double free?)
404An attempt to
405.Fn free
406or
407.Fn realloc
408an unallocated pointer was made.
409.It Dq chunk is already free
410There was an attempt to free a chunk that had already been freed.
411.It Dq modified chunk-pointer
412The pointer passed to
413.Fn free
414or
415.Fn realloc
416has been modified.
417.It Dq recursive call
418An attempt was made to call recursively into these functions, i.e., from a
419signal handler.
420This behavior is not supported.
421In particular, signal handlers should
422.Em not
423use any of the
424.Fn malloc
425functions nor utilize any other functions which may call
426.Fn malloc
427(e.g.,
428.Xr stdio 3
429routines).
430.It Dq unknown char in MALLOC_OPTIONS
431We found something we didn't understand.
432.It Dq malloc cache overflow/underflow
433The internal malloc page cache has been corrupted.
434.It Dq malloc free slot lost
435The internal malloc page cache has been corrupted.
436.It Dq guard size
437An inconsistent guard size was detected.
438.It any other error
439.Fn malloc
440detected an internal error;
441consult sources and/or wizards.
442.El
443.Sh SEE ALSO 599.Sh SEE ALSO
444.Xr brk 2 , 600.Xr brk 2 ,
445.Xr mmap 2 , 601.Xr mmap 2 ,
446.Xr munmap 2 , 602.Xr munmap 2 ,
447.Xr alloca 3 , 603.Xr alloca 3 ,
448.Xr getpagesize 3 , 604.Xr getpagesize 3 ,
449.Xr posix_memalign 3 605.Xr posix_memalign 3 ,
606.Xr sysconf 3
450.Sh STANDARDS 607.Sh STANDARDS
451The 608The
452.Fn malloc 609.Fn malloc ,
453function conforms to 610.Fn calloc ,
611.Fn realloc ,
612and
613.Fn free
614functions conform to
454.St -ansiC . 615.St -ansiC .
455.Sh HISTORY 616.Sh HISTORY
456A 617A
@@ -496,6 +657,77 @@ random.
496A rewrite by Otto Moerbeek introducing a new central data structure and more 657A rewrite by Otto Moerbeek introducing a new central data structure and more
497randomization appeared in 658randomization appeared in
498.Ox 4.4 . 659.Ox 4.4 .
660.Pp
661The
499.Fn reallocarray 662.Fn reallocarray
500appeared in 663function appeared in
501.Ox 5.6 . 664.Ox 5.6 .
665.Pp
666The
667.Fn cfree
668function appeared in SunOS 4.x.
669.Sh CAVEATS
670The
671.Fn calloc
672function checks for integer overflow in
673.Ox
674and most other modern platforms.
675Software targeting ancient platforms should not rely on this behavior.
676.Pp
677The
678.Fn malloc ,
679.Fn calloc ,
680and
681.Fn realloc
682functions have implementation defined behavior when
683.Fa size
684or
685.Fa nmemb
686are zero.
687.Pp
688Allocation of a zero size object returns a pointer to an access protected zero
689size object.
690Many zero-sized objects can be placed consecutively in shared
691protected pages.
692The minimum size of the protection on each object is suitably aligned and
693sized as previously stated, but the protection may extend further depending
694on where in a protected zone the object lands.
695Attempting to access these objects will generate a
696.Pq Dv SIGSEGV
697exception.
698.Pp
699When using
700.Fn malloc ,
701be wary of signed integer and
702.Vt size_t
703overflow especially when you
704have multiplication in the
705.Fa size
706argument.
707.Pp
708Signed integer overflow will cause undefined behavior which compilers
709typically handle by wrapping back around to negative numbers.
710Depending on the input, this can result in allocating more or less
711memory than you intended.
712.Pp
713An unsigned overflow has defined behavior which will wrap back around and you
714will receive less memory than you intended.
715.Pp
716A signed or unsigned integer overflow is a
717.Em security
718risk if you end up allocating less memory than you intended.
719Your code may corrupt the heap by writing beyond the memory that you
720were allocated.
721An attacker may be able to leverage this heap corruption to convince your
722program to execute arbitrary code.
723.Pp
724Consider using
725.Fn calloc
726or
727.Fn reallocarray
728instead of using multiplication in
729.Fn malloc
730and
731.Fn realloc
732to avoid these problems on
733.Ox .