xref: /netbsd-src/sys/kern/kern_malloc.c (revision 10c5b0232091c5643fb7fcc69b901d4009c696a7)
1*10c5b023Smaxv /*	$NetBSD: kern_malloc.c,v 1.158 2019/11/14 16:23:52 maxv Exp $	*/
2aad01611Sagc 
3aad01611Sagc /*
4aad01611Sagc  * Copyright (c) 1987, 1991, 1993
5aad01611Sagc  *	The Regents of the University of California.  All rights reserved.
6aad01611Sagc  *
7aad01611Sagc  * Redistribution and use in source and binary forms, with or without
8aad01611Sagc  * modification, are permitted provided that the following conditions
9aad01611Sagc  * are met:
10aad01611Sagc  * 1. Redistributions of source code must retain the above copyright
11aad01611Sagc  *    notice, this list of conditions and the following disclaimer.
12aad01611Sagc  * 2. Redistributions in binary form must reproduce the above copyright
13aad01611Sagc  *    notice, this list of conditions and the following disclaimer in the
14aad01611Sagc  *    documentation and/or other materials provided with the distribution.
15aad01611Sagc  * 3. Neither the name of the University nor the names of its contributors
16aad01611Sagc  *    may be used to endorse or promote products derived from this software
17aad01611Sagc  *    without specific prior written permission.
18aad01611Sagc  *
19aad01611Sagc  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20aad01611Sagc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21aad01611Sagc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22aad01611Sagc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23aad01611Sagc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24aad01611Sagc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25aad01611Sagc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26aad01611Sagc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27aad01611Sagc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28aad01611Sagc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29aad01611Sagc  * SUCH DAMAGE.
30aad01611Sagc  *
31aad01611Sagc  *	@(#)kern_malloc.c	8.4 (Berkeley) 5/20/95
32aad01611Sagc  */
33cf92afd6Scgd 
3461f28255Scgd /*
3534c5a58bSchristos  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
3661f28255Scgd  *
3761f28255Scgd  * Redistribution and use in source and binary forms, with or without
3861f28255Scgd  * modification, are permitted provided that the following conditions
3961f28255Scgd  * are met:
4061f28255Scgd  * 1. Redistributions of source code must retain the above copyright
4161f28255Scgd  *    notice, this list of conditions and the following disclaimer.
4261f28255Scgd  * 2. Redistributions in binary form must reproduce the above copyright
4361f28255Scgd  *    notice, this list of conditions and the following disclaimer in the
4461f28255Scgd  *    documentation and/or other materials provided with the distribution.
4561f28255Scgd  * 3. All advertising materials mentioning features or use of this software
4661f28255Scgd  *    must display the following acknowledgement:
4761f28255Scgd  *	This product includes software developed by the University of
4861f28255Scgd  *	California, Berkeley and its contributors.
4961f28255Scgd  * 4. Neither the name of the University nor the names of its contributors
5061f28255Scgd  *    may be used to endorse or promote products derived from this software
5161f28255Scgd  *    without specific prior written permission.
5261f28255Scgd  *
5361f28255Scgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5461f28255Scgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5561f28255Scgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5661f28255Scgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5761f28255Scgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5861f28255Scgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5961f28255Scgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6061f28255Scgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6161f28255Scgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6261f28255Scgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6361f28255Scgd  * SUCH DAMAGE.
6461f28255Scgd  *
65e5bc90f4Sfvdl  *	@(#)kern_malloc.c	8.4 (Berkeley) 5/20/95
6661f28255Scgd  */
6761f28255Scgd 
684b760398Srmind /*
694b760398Srmind  * Wrapper interface for obsolete malloc(9).
704b760398Srmind  */
714b760398Srmind 
72adc783d5Slukem #include <sys/cdefs.h>
73*10c5b023Smaxv __KERNEL_RCSID(0, "$NetBSD: kern_malloc.c,v 1.158 2019/11/14 16:23:52 maxv Exp $");
74d9048520Smrg 
7521edb992Smycroft #include <sys/param.h>
7621edb992Smycroft #include <sys/malloc.h>
77e62ee4d4Spara #include <sys/kmem.h>
78acb25765Smaxv #include <sys/asan.h>
79*10c5b023Smaxv #include <sys/msan.h>
80acb25765Smaxv 
814b760398Srmind /*
824b760398Srmind  * Built-in malloc types.  Note: ought to be removed.
834b760398Srmind  */
844b760398Srmind MALLOC_DEFINE(M_DEVBUF, "devbuf", "device driver memory");
854b760398Srmind MALLOC_DEFINE(M_DMAMAP, "DMA map", "bus_dma(9) structures");
864b760398Srmind MALLOC_DEFINE(M_FREE, "free", "should be on free list");
874b760398Srmind MALLOC_DEFINE(M_TEMP, "temp", "misc. temporary data buffers");
884b760398Srmind MALLOC_DEFINE(M_RTABLE, "routetbl", "routing tables");
894b760398Srmind MALLOC_DEFINE(M_FTABLE, "fragtbl", "fragment reassembly header");
904b760398Srmind MALLOC_DEFINE(M_UFSMNT, "UFS mount", "UFS mount structure");
914b760398Srmind MALLOC_DEFINE(M_NETADDR, "Export Host", "Export host address structure");
924b760398Srmind MALLOC_DEFINE(M_MRTABLE, "mrt", "multicast routing tables");
937b30910bSthorpej 
944b760398Srmind /*
954b760398Srmind  * Header contains total size, including the header itself.
964b760398Srmind  */
97e62ee4d4Spara struct malloc_header {
98e62ee4d4Spara 	size_t mh_size;
99ba43769bSmaxv #ifdef KASAN
100ba43769bSmaxv 	size_t mh_rqsz;
101ba43769bSmaxv #endif
10228f4072dSmrg } __aligned(ALIGNBYTES + 1);
103e62ee4d4Spara 
10461f28255Scgd void *
kern_malloc(unsigned long reqsize,int flags)10538f575d1Smartin kern_malloc(unsigned long reqsize, int flags)
10661f28255Scgd {
1073ad48751Srmind 	const int kmflags = (flags & M_NOWAIT) ? KM_NOSLEEP : KM_SLEEP;
108740156e9Smaxv #ifdef KASAN
10938f575d1Smartin 	const size_t origsize = reqsize;
110740156e9Smaxv #endif
11138f575d1Smartin 	size_t size = reqsize;
11276ee9effSdrochner 	size_t allocsize, hdroffset;
113e62ee4d4Spara 	struct malloc_header *mh;
114e62ee4d4Spara 	void *p;
11561f28255Scgd 
116acb25765Smaxv 	kasan_add_redzone(&size);
117acb25765Smaxv 
11876ee9effSdrochner 	if (size >= PAGE_SIZE) {
119f08cc415Smartin 		if (size > (ULONG_MAX-PAGE_SIZE))
120f08cc415Smartin 			allocsize = ULONG_MAX;	/* this will fail later */
121f08cc415Smartin 		else
12276ee9effSdrochner 			allocsize = PAGE_SIZE + size; /* for page alignment */
12376ee9effSdrochner 		hdroffset = PAGE_SIZE - sizeof(struct malloc_header);
12476ee9effSdrochner 	} else {
12576ee9effSdrochner 		allocsize = sizeof(struct malloc_header) + size;
12676ee9effSdrochner 		hdroffset = 0;
12776ee9effSdrochner 	}
12876ee9effSdrochner 
129e62ee4d4Spara 	p = kmem_intr_alloc(allocsize, kmflags);
130e62ee4d4Spara 	if (p == NULL)
131e62ee4d4Spara 		return NULL;
1320711fdafSchs 
133*10c5b023Smaxv 	kmsan_mark(p, allocsize, KMSAN_STATE_UNINIT);
134*10c5b023Smaxv 	kmsan_orig(p, allocsize, KMSAN_TYPE_MALLOC, __RET_ADDR);
135*10c5b023Smaxv 
136e62ee4d4Spara 	if ((flags & M_ZERO) != 0) {
137e62ee4d4Spara 		memset(p, 0, allocsize);
1380711fdafSchs 	}
13976ee9effSdrochner 	mh = (void *)((char *)p + hdroffset);
14076ee9effSdrochner 	mh->mh_size = allocsize - hdroffset;
141ba43769bSmaxv #ifdef KASAN
142ba43769bSmaxv 	mh->mh_rqsz = origsize;
143ba43769bSmaxv #endif
144b120dbbaSmaxv 	mh++;
1453d9ffd41Scgd 
146ae73490eSmaxv 	kasan_mark(mh, origsize, size, KASAN_MALLOC_REDZONE);
147acb25765Smaxv 
148b120dbbaSmaxv 	return mh;
14961f28255Scgd }
15061f28255Scgd 
15161f28255Scgd void
kern_free(void * addr)152dbd08155Sdsl kern_free(void *addr)
15361f28255Scgd {
154e62ee4d4Spara 	struct malloc_header *mh;
15561f28255Scgd 
156e62ee4d4Spara 	mh = addr;
157e62ee4d4Spara 	mh--;
158bbd3d01dSthorpej 
159cdf8841dSmaxv 	kasan_mark(addr, mh->mh_size - sizeof(struct malloc_header),
160ae73490eSmaxv 	    mh->mh_size - sizeof(struct malloc_header), KASAN_MALLOC_REDZONE);
161acb25765Smaxv 
162*10c5b023Smaxv 	if (mh->mh_size >= PAGE_SIZE + sizeof(struct malloc_header)) {
163*10c5b023Smaxv 		kmsan_mark((char *)addr - PAGE_SIZE,
164*10c5b023Smaxv 		    mh->mh_size + PAGE_SIZE - sizeof(struct malloc_header),
165*10c5b023Smaxv 		    KMSAN_STATE_INITED);
16676ee9effSdrochner 		kmem_intr_free((char *)addr - PAGE_SIZE,
16776ee9effSdrochner 		    mh->mh_size + PAGE_SIZE - sizeof(struct malloc_header));
168*10c5b023Smaxv 	} else {
169*10c5b023Smaxv 		kmsan_mark(mh, mh->mh_size, KMSAN_STATE_INITED);
170e62ee4d4Spara 		kmem_intr_free(mh, mh->mh_size);
17161f28255Scgd 	}
172*10c5b023Smaxv }
17361f28255Scgd 
174f8ed9333Scgd void *
kern_realloc(void * curaddr,unsigned long newsize,int flags)175dbd08155Sdsl kern_realloc(void *curaddr, unsigned long newsize, int flags)
176f8ed9333Scgd {
177e62ee4d4Spara 	struct malloc_header *mh;
1785f7ccd16Sthorpej 	unsigned long cursize;
179f8ed9333Scgd 	void *newaddr;
180f8ed9333Scgd 
181f8ed9333Scgd 	/*
18276994984Senami 	 * realloc() with a NULL pointer is the same as malloc().
183f8ed9333Scgd 	 */
184f8ed9333Scgd 	if (curaddr == NULL)
1854b760398Srmind 		return malloc(newsize, ksp, flags);
186f8ed9333Scgd 
187f8ed9333Scgd 	/*
18876994984Senami 	 * realloc() with zero size is the same as free().
189f8ed9333Scgd 	 */
190f8ed9333Scgd 	if (newsize == 0) {
191b1934809Sthorpej 		free(curaddr, ksp);
1924b760398Srmind 		return NULL;
193f8ed9333Scgd 	}
194f8ed9333Scgd 
195ad4f28d1Sad 	if ((flags & M_NOWAIT) == 0) {
196a67bae0bSyamt 		ASSERT_SLEEPABLE();
197ad4f28d1Sad 	}
19867a875a8Sthorpej 
199e62ee4d4Spara 	mh = curaddr;
200e62ee4d4Spara 	mh--;
201f8ed9333Scgd 
202ba43769bSmaxv #ifdef KASAN
203ba43769bSmaxv 	cursize = mh->mh_rqsz;
204ba43769bSmaxv #else
2053ad48751Srmind 	cursize = mh->mh_size - sizeof(struct malloc_header);
206ba43769bSmaxv #endif
207f8ed9333Scgd 
208f8ed9333Scgd 	/*
209f8ed9333Scgd 	 * If we already actually have as much as they want, we're done.
210f8ed9333Scgd 	 */
211f8ed9333Scgd 	if (newsize <= cursize)
2124b760398Srmind 		return curaddr;
213f8ed9333Scgd 
214f8ed9333Scgd 	/*
215f8ed9333Scgd 	 * Can't satisfy the allocation with the existing block.
216f8ed9333Scgd 	 * Allocate a new one and copy the data.
217f8ed9333Scgd 	 */
218b1934809Sthorpej 	newaddr = malloc(newsize, ksp, flags);
219e633df2aSthorpej 	if (__predict_false(newaddr == NULL)) {
220f8ed9333Scgd 		/*
22176994984Senami 		 * malloc() failed, because flags included M_NOWAIT.
222f8ed9333Scgd 		 * Return NULL to indicate that failure.  The old
223f8ed9333Scgd 		 * pointer is still valid.
224f8ed9333Scgd 		 */
2254b760398Srmind 		return NULL;
226f8ed9333Scgd 	}
227275d1554Sperry 	memcpy(newaddr, curaddr, cursize);
228f8ed9333Scgd 
229f8ed9333Scgd 	/*
230f8ed9333Scgd 	 * We were successful: free the old allocation and return
231f8ed9333Scgd 	 * the new one.
232f8ed9333Scgd 	 */
233b1934809Sthorpej 	free(curaddr, ksp);
2344b760398Srmind 	return newaddr;
235f8ed9333Scgd }
236