user_environment.c (7730B)
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 { 78 return; 79 } 80 81 void 82 read_random(void *buf, size_t size) 83 { 84 memset(buf, 'A', size); 85 return; 86 } 87 88 void 89 finish_random(void) 90 { 91 return; 92 } 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