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