/src/usrsctp/usrsctplib/user_environment.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*- |
2 | | * Copyright (c) 2009-2010 Brad Penoff |
3 | | * Copyright (c) 2009-2010 Humaira Kamal |
4 | | * Copyright (c) 2011-2012 Irene Ruengeler |
5 | | * Copyright (c) 2011-2012 Michael Tuexen |
6 | | * |
7 | | * All rights reserved. |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions |
11 | | * are met: |
12 | | * 1. Redistributions of source code must retain the above copyright |
13 | | * notice, this list of conditions and the following disclaimer. |
14 | | * 2. Redistributions in binary form must reproduce the above copyright |
15 | | * notice, this list of conditions and the following disclaimer in the |
16 | | * documentation and/or other materials provided with the distribution. |
17 | | * |
18 | | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
19 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
20 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
21 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE |
22 | | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
24 | | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
25 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
26 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
27 | | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
28 | | * SUCH DAMAGE. |
29 | | */ |
30 | | |
31 | | /* __Userspace__ */ |
32 | | |
33 | | #if defined(_WIN32) |
34 | | #if !defined(_CRT_RAND_S) && !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
35 | | #define _CRT_RAND_S |
36 | | #endif |
37 | | #else |
38 | | #include <stdint.h> |
39 | | #include <netinet/sctp_os_userspace.h> |
40 | | #endif |
41 | | #ifdef INVARIANTS |
42 | | #include <netinet/sctp_pcb.h> |
43 | | #endif |
44 | | #include <user_environment.h> |
45 | | #include <sys/types.h> |
46 | | /* #include <sys/param.h> defines MIN */ |
47 | | #if !defined(MIN) |
48 | | #define MIN(arg1,arg2) ((arg1) < (arg2) ? (arg1) : (arg2)) |
49 | | #endif |
50 | | |
51 | | #define uHZ 1000 |
52 | | |
53 | | /* See user_include/user_environment.h for comments about these variables */ |
54 | | int maxsockets = 25600; |
55 | | int hz = uHZ; |
56 | | int ip_defttl = 64; |
57 | | int ipport_firstauto = 49152, ipport_lastauto = 65535; |
58 | | int nmbclusters = 65536; |
59 | | |
60 | | /* Source ip_output.c. extern'd in ip_var.h */ |
61 | | u_short ip_id = 0; /*__Userspace__ TODO Should it be initialized to zero? */ |
62 | | |
63 | | /* used in user_include/user_atomic.h in order to make the operations |
64 | | * defined there truly atomic |
65 | | */ |
66 | | userland_mutex_t atomic_mtx; |
67 | | |
68 | | /* If the entropy device is not loaded, make a token effort to |
69 | | * provide _some_ kind of randomness. This should only be used |
70 | | * inside other RNG's, like arc4random(9). |
71 | | */ |
72 | | #if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) |
73 | | #include <string.h> |
74 | | |
75 | | void |
76 | | init_random(void) |
77 | 3 | { |
78 | 3 | return; |
79 | 3 | } |
80 | | |
81 | | void |
82 | | read_random(void *buf, size_t size) |
83 | 27.0k | { |
84 | 27.0k | memset(buf, 'A', size); |
85 | 27.0k | return; |
86 | 27.0k | } |
87 | | |
88 | | void |
89 | | finish_random(void) |
90 | 0 | { |
91 | 0 | return; |
92 | 0 | } |
93 | | /* This define can be used to optionally use OpenSSL's random number utility, |
94 | | * which is capable of bypassing the chromium sandbox which normally would |
95 | | * prevent opening files, including /dev/urandom. |
96 | | */ |
97 | | #elif defined(SCTP_USE_OPENSSL_RAND) |
98 | | #include <openssl/rand.h> |
99 | | |
100 | | /* Requiring BoringSSL because it guarantees that RAND_bytes will succeed. */ |
101 | | #ifndef OPENSSL_IS_BORINGSSL |
102 | | #error Only BoringSSL is supported with SCTP_USE_OPENSSL_RAND. |
103 | | #endif |
104 | | |
105 | | void |
106 | | init_random(void) |
107 | | { |
108 | | return; |
109 | | } |
110 | | |
111 | | void |
112 | | read_random(void *buf, size_t size) |
113 | | { |
114 | | RAND_bytes((uint8_t *)buf, size); |
115 | | return; |
116 | | } |
117 | | |
118 | | void |
119 | | finish_random(void) |
120 | | { |
121 | | return; |
122 | | } |
123 | | #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__Bitrig__) |
124 | | #include <stdlib.h> |
125 | | |
126 | | void |
127 | | init_random(void) |
128 | | { |
129 | | return; |
130 | | } |
131 | | |
132 | | void |
133 | | read_random(void *buf, size_t size) |
134 | | { |
135 | | arc4random_buf(buf, size); |
136 | | return; |
137 | | } |
138 | | |
139 | | void |
140 | | finish_random(void) |
141 | | { |
142 | | return; |
143 | | } |
144 | | #elif defined(_WIN32) |
145 | | #include <stdlib.h> |
146 | | |
147 | | void |
148 | | init_random(void) |
149 | | { |
150 | | return; |
151 | | } |
152 | | |
153 | | void |
154 | | read_random(void *buf, size_t size) |
155 | | { |
156 | | unsigned int randval; |
157 | | size_t position, remaining; |
158 | | |
159 | | position = 0; |
160 | | while (position < size) { |
161 | | if (rand_s(&randval) == 0) { |
162 | | remaining = MIN(size - position, sizeof(unsigned int)); |
163 | | memcpy((char *)buf + position, &randval, remaining); |
164 | | position += sizeof(unsigned int); |
165 | | } |
166 | | } |
167 | | return; |
168 | | } |
169 | | |
170 | | void |
171 | | finish_random(void) |
172 | | { |
173 | | return; |
174 | | } |
175 | | #elif (defined(__ANDROID__) && (__ANDROID_API__ < 28)) || defined(__QNX__) || defined(__EMSCRIPTEN__) |
176 | | #include <fcntl.h> |
177 | | |
178 | | static int fd = -1; |
179 | | |
180 | | void |
181 | | init_random(void) |
182 | | { |
183 | | fd = open("/dev/urandom", O_RDONLY); |
184 | | return; |
185 | | } |
186 | | |
187 | | void |
188 | | read_random(void *buf, size_t size) |
189 | | { |
190 | | size_t position; |
191 | | ssize_t n; |
192 | | |
193 | | position = 0; |
194 | | while (position < size) { |
195 | | n = read(fd, (char *)buf + position, size - position); |
196 | | if (n > 0) { |
197 | | position += n; |
198 | | } |
199 | | } |
200 | | return; |
201 | | } |
202 | | |
203 | | void |
204 | | finish_random(void) |
205 | | { |
206 | | close(fd); |
207 | | return; |
208 | | } |
209 | | #elif defined(__ANDROID__) && (__ANDROID_API__ >= 28) |
210 | | #include <sys/random.h> |
211 | | |
212 | | void |
213 | | init_random(void) |
214 | | { |
215 | | return; |
216 | | } |
217 | | |
218 | | void |
219 | | read_random(void *buf, size_t size) |
220 | | { |
221 | | size_t position; |
222 | | ssize_t n; |
223 | | |
224 | | position = 0; |
225 | | while (position < size) { |
226 | | n = getrandom((char *)buf + position, size - position, 0); |
227 | | if (n > 0) { |
228 | | position += n; |
229 | | } |
230 | | } |
231 | | return; |
232 | | } |
233 | | |
234 | | void |
235 | | finish_random(void) |
236 | | { |
237 | | return; |
238 | | } |
239 | | #elif defined(__linux__) |
240 | | #include <fcntl.h> |
241 | | #include <unistd.h> |
242 | | #include <sys/syscall.h> |
243 | | |
244 | | #if defined(__has_feature) |
245 | | #if __has_feature(memory_sanitizer) |
246 | | void __msan_unpoison(void *, size_t); |
247 | | #endif |
248 | | #endif |
249 | | |
250 | | #ifdef __NR_getrandom |
251 | | #if !defined(GRND_NONBLOCK) |
252 | | #define GRND_NONBLOCK 1 |
253 | | #endif |
254 | | static int getrandom_available = 0; |
255 | | #endif |
256 | | static int fd = -1; |
257 | | |
258 | | void |
259 | | init_random(void) |
260 | | { |
261 | | #ifdef __NR_getrandom |
262 | | char dummy; |
263 | | ssize_t n = syscall(__NR_getrandom, &dummy, sizeof(dummy), GRND_NONBLOCK); |
264 | | if (n > 0 || errno == EINTR || errno == EAGAIN) { |
265 | | /* Either getrandom succeeded, was interrupted or is waiting for entropy; |
266 | | * all of which mean the syscall is available. |
267 | | */ |
268 | | getrandom_available = 1; |
269 | | } else { |
270 | | #ifdef INVARIANTS |
271 | | if (errno != ENOSYS) { |
272 | | panic("getrandom syscall returned unexpected error: %d", errno); |
273 | | } |
274 | | #endif |
275 | | /* If the syscall isn't available, fall back to /dev/urandom. */ |
276 | | #endif |
277 | | fd = open("/dev/urandom", O_RDONLY); |
278 | | #ifdef __NR_getrandom |
279 | | } |
280 | | #endif |
281 | | return; |
282 | | } |
283 | | |
284 | | void |
285 | | read_random(void *buf, size_t size) |
286 | | { |
287 | | size_t position; |
288 | | ssize_t n; |
289 | | |
290 | | position = 0; |
291 | | while (position < size) { |
292 | | #ifdef __NR_getrandom |
293 | | if (getrandom_available) { |
294 | | /* Using syscall directly because getrandom isn't present in glibc < 2.25. |
295 | | */ |
296 | | n = syscall(__NR_getrandom, (char *)buf + position, size - position, 0); |
297 | | if (n > 0) { |
298 | | #if defined(__has_feature) |
299 | | #if __has_feature(memory_sanitizer) |
300 | | /* Need to do this because MSan doesn't realize that syscall has |
301 | | * initialized the output buffer. |
302 | | */ |
303 | | __msan_unpoison(buf + position, n); |
304 | | #endif |
305 | | #endif |
306 | | position += n; |
307 | | } else if (errno != EINTR && errno != EAGAIN) { |
308 | | #ifdef INVARIANTS |
309 | | panic("getrandom syscall returned unexpected error: %d", errno); |
310 | | #endif |
311 | | } |
312 | | } else |
313 | | #endif /* __NR_getrandom */ |
314 | | { |
315 | | n = read(fd, (char *)buf + position, size - position); |
316 | | if (n > 0) { |
317 | | position += n; |
318 | | } |
319 | | } |
320 | | } |
321 | | return; |
322 | | } |
323 | | |
324 | | void |
325 | | finish_random(void) |
326 | | { |
327 | | if (fd != -1) { |
328 | | close(fd); |
329 | | } |
330 | | return; |
331 | | } |
332 | | #elif defined(__Fuchsia__) |
333 | | #include <zircon/syscalls.h> |
334 | | |
335 | | void |
336 | | init_random(void) |
337 | | { |
338 | | return; |
339 | | } |
340 | | |
341 | | void |
342 | | read_random(void *buf, size_t size) |
343 | | { |
344 | | zx_cprng_draw(buf, size); |
345 | | return; |
346 | | } |
347 | | |
348 | | void |
349 | | finish_random(void) |
350 | | { |
351 | | return; |
352 | | } |
353 | | #elif defined(__native_client__) |
354 | | #include <nacl/nacl_random.h> |
355 | | |
356 | | void |
357 | | init_random(void) |
358 | | { |
359 | | return; |
360 | | } |
361 | | |
362 | | void |
363 | | read_random(void *buf, size_t size) |
364 | | { |
365 | | size_t position; |
366 | | size_t n; |
367 | | |
368 | | position = 0; |
369 | | while (position < size) { |
370 | | if (nacl_secure_random((char *)buf + position, size - position, &n) == 0) { |
371 | | position += n; |
372 | | } |
373 | | } |
374 | | return; |
375 | | } |
376 | | |
377 | | void |
378 | | finish_random(void) |
379 | | { |
380 | | return; |
381 | | } |
382 | | #else |
383 | | #error "Unknown platform. Please provide platform specific RNG." |
384 | | #endif |