/src/SockFuzzer/fuzz/fakes/mbuf.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2021 Google LLC |
3 | | * |
4 | | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
5 | | * |
6 | | * This file contains Original Code and/or Modifications of Original Code |
7 | | * as defined in and that are subject to the Apple Public Source License |
8 | | * Version 2.0 (the 'License'). You may not use this file except in |
9 | | * compliance with the License. The rights granted to you under the License |
10 | | * may not be used to create, or enable the creation or redistribution of, |
11 | | * unlawful or unlicensed copies of an Apple operating system, or to |
12 | | * circumvent, violate, or enable the circumvention or violation of, any |
13 | | * terms of an Apple operating system software license agreement. |
14 | | * |
15 | | * Please obtain a copy of the License at |
16 | | * http://www.opensource.apple.com/apsl/ and read it before using this file. |
17 | | * |
18 | | * The Original Code and all software distributed under the License are |
19 | | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
20 | | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
22 | | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
23 | | * Please see the License for the specific language governing rights and |
24 | | * limitations under the License. |
25 | | * |
26 | | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
27 | | */ |
28 | | |
29 | | #include "bsd/machine/param.h" |
30 | | #include "bsd/sys/mbuf.h" |
31 | | |
32 | | // We link these in from libc/asan |
33 | | void* malloc(size_t size); |
34 | | void* calloc(size_t nmemb, size_t size); |
35 | | void free(void* ptr); |
36 | | int posix_memalign(void** memptr, size_t alignment, size_t size); |
37 | | |
38 | | typedef struct { |
39 | | size_t bufsize; |
40 | | // Must we always return clusters? |
41 | | bool cluster_cache; |
42 | | } mcache_t; |
43 | | |
44 | | mcache_t* mcache_create(const char* name, size_t bufsize, size_t align, |
45 | 7 | u_int32_t flags, int wait) { |
46 | 7 | mcache_t* cache = (mcache_t*)malloc(sizeof(mcache_t)); |
47 | 7 | cache->bufsize = bufsize; |
48 | 7 | cache->cluster_cache = false; |
49 | 7 | return cache; |
50 | 7 | } |
51 | | |
52 | | // type doesn't match but we just need the address |
53 | | void mbuf_cslab_alloc(void); |
54 | | |
55 | | mcache_t* mcache_create_ext(const char* name, size_t bufsize, void* allocfn, |
56 | | void* freefn, void* auditfn, void* logfn, |
57 | | void* notifyfn, void* arg, u_int32_t flags, |
58 | 7 | int wait) { |
59 | 7 | mcache_t* cache = (mcache_t*)malloc(sizeof(mcache_t)); |
60 | 7 | cache->bufsize = bufsize; |
61 | 7 | cache->cluster_cache = allocfn == mbuf_cslab_alloc; |
62 | 7 | return cache; |
63 | 7 | } |
64 | | |
65 | 0 | void assfail() { assert(false); } |
66 | | |
67 | | struct mbuf* mbuf_create(const uint8_t* data, size_t size, bool is_header, |
68 | 949k | bool force_ext, int mtype, int pktflags) { |
69 | 949k | struct mbuf* m = NULL; |
70 | 949k | assert(sizeof(struct mbuf) == MSIZE); |
71 | 949k | if (posix_memalign((void**)&m, MSIZE, sizeof(struct mbuf))) { |
72 | 0 | return NULL; |
73 | 0 | } |
74 | 949k | memset((void*)m, 0, sizeof(struct mbuf)); |
75 | 949k | m->m_type = mtype; |
76 | | // TODO: use fuzzed data to create all kinds of mbuf chains |
77 | 949k | size_t max_size = MBIGCLBYTES; |
78 | 949k | if (njcl > 0) { |
79 | 949k | max_size = njclbytes; |
80 | 949k | } |
81 | 949k | if (size >= max_size) { |
82 | 22 | size = max_size - 1; |
83 | 22 | } |
84 | | |
85 | 949k | if (force_ext || size > sizeof(m->M_dat.MH.MH_dat.MH_databuf)) { |
86 | 133k | m->m_flags = M_EXT; |
87 | 133k | m->m_data = m->m_ext.ext_buf = (caddr_t)calloc(1, size); |
88 | 133k | m->m_ext.ext_size = size; |
89 | | |
90 | 133k | struct ext_ref* rfa = (struct ext_ref*)calloc(1, sizeof(struct ext_ref)); |
91 | 133k | rfa->refcnt = 1; |
92 | 133k | rfa->minref = 1; |
93 | 133k | int EXTF_COMPOSITE = 0x1; |
94 | 133k | rfa->flags = EXTF_COMPOSITE; |
95 | 133k | m->m_ext.ext_refflags = (struct ext_ref*)rfa; |
96 | 815k | } else { |
97 | 815k | m->m_flags = M_PKTHDR; |
98 | 815k | m->m_data = m->m_pktdat; |
99 | 815k | } |
100 | | |
101 | 949k | if (data) memcpy(m->m_data, data, size); |
102 | 949k | m->m_len = size; |
103 | 949k | if (is_header) { |
104 | 936k | m->m_flags |= M_PKTHDR; |
105 | 936k | m->m_pkthdr.len = m->m_len; |
106 | 936k | m->m_pkthdr.redzone = ((u_int32_t)(uintptr_t)m); |
107 | 936k | m->m_pkthdr.pkt_flags = pktflags; |
108 | 936k | } |
109 | | |
110 | 949k | assert(m->m_len <= ((njcl > 0) ? njclbytes : MBIGCLBYTES)); |
111 | | |
112 | 0 | return m; |
113 | 949k | } |
114 | | |
115 | 296k | void* mcache_alloc(mcache_t* cp, int flags) { |
116 | 296k | if (cp->cluster_cache) { |
117 | 12.7k | return mbuf_create(NULL, cp->bufsize, false, cp->cluster_cache, MT_FREE, 0); |
118 | 12.7k | } |
119 | | |
120 | 283k | void* m = NULL; |
121 | 283k | if (posix_memalign((void**)&m, MSIZE, cp->bufsize)) { |
122 | 0 | return NULL; |
123 | 0 | } |
124 | 283k | return m; |
125 | 283k | } |
126 | | |
127 | 163k | uint16_t m_decref(struct mbuf* m) { |
128 | 163k | struct ext_ref* rfa = m->m_ext.ext_refflags; |
129 | 163k | if (rfa) { |
130 | 163k | rfa->refcnt--; |
131 | 163k | return rfa->refcnt; |
132 | 163k | } |
133 | 0 | return 0; |
134 | 163k | } |
135 | | |
136 | 1.22M | struct mbuf* m_free(struct mbuf* m) { |
137 | 1.22M | if ((m->m_flags & M_EXT)) { |
138 | 163k | uint16_t refcnt = m_decref(m); |
139 | 163k | if (!refcnt) { |
140 | 135k | free(m->m_ext.ext_buf); |
141 | 135k | free(m->m_ext.ext_refflags); |
142 | 135k | } |
143 | 163k | } |
144 | 1.22M | struct mbuf* ret = m->m_next; |
145 | 1.22M | free(m); |
146 | 1.22M | return ret; |
147 | 1.22M | } |
148 | | |
149 | 0 | void mcache_free(mcache_t* cp, void* buf) { |
150 | 0 | if (cp->cluster_cache) { |
151 | 0 | m_free((struct mbuf*)buf); |
152 | 0 | } else { |
153 | 0 | free(buf); |
154 | 0 | } |
155 | 0 | } |
156 | | |
157 | 1 | void mcache_init() { |
158 | | // Nothing to do for mocked case. |
159 | 1 | } |
160 | | |
161 | 0 | void mcache_reap_now() { assert(false); } |
162 | | |
163 | 0 | int mcache_alloc_ext(mcache_t* cp, void** list, unsigned int num, int wait) { |
164 | 0 | struct mbuf* m = (struct mbuf*)calloc(1, sizeof(struct mbuf)); |
165 | 0 | m->m_hdr.mh_next = NULL; |
166 | 0 | m->m_hdr.mh_nextpkt = NULL; |
167 | 0 | m->m_type = MT_FREE; |
168 | 0 | m->m_flags = M_EXT; |
169 | 0 | m->m_hdr.mh_data = (caddr_t)calloc(1, num * cp->bufsize); |
170 | 0 | m->m_hdr.mh_len = num * cp->bufsize; |
171 | 0 | *list = m; |
172 | 0 | return 1; |
173 | 0 | } |
174 | | |
175 | 0 | void mcache_audit_cache() { assert(false); } |
176 | | |
177 | 0 | void mcache_audit_free_verify() { assert(false); } |
178 | | |
179 | 0 | void mcache_audit_free_verify_set() { assert(false); } |
180 | | |
181 | 0 | void mcache_bkt_isempty() { assert(false); } |
182 | | |
183 | 0 | void mcache_buffer_log() { assert(false); } |
184 | | |
185 | 0 | unsigned int mcache_cache_line_size() { |
186 | 0 | return 64; |
187 | 0 | } |
188 | | |
189 | 0 | void mcache_dump_mca() { assert(false); } |
190 | | |
191 | 0 | void mcache_free_ext() { assert(false); } |
192 | | |
193 | 1 | unsigned int mcache_getflags() { return 0; } |
194 | | |
195 | 0 | void mcache_purge_cache() { assert(false); } |
196 | | |
197 | 0 | void mcache_reap() { assert(false); } |
198 | | |
199 | 0 | void mcache_set_pattern() { assert(false); } |
200 | | |
201 | 0 | void mcache_waiter_dec() { assert(false); } |
202 | | |
203 | 0 | void mcache_waiter_inc() { assert(false); } |