1 /* 2 * OS specific functions for UNIX/POSIX systems 3 * Copyright (c) 2005-2009, Jouni Malinen <j (at) w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include <time.h> 12 #include <sys/wait.h> 13 14 #ifdef ANDROID 15 #include <sys/capability.h> 16 #include <sys/prctl.h> 17 #include <private/android_filesystem_config.h> 18 #endif /* ANDROID */ 19 20 #ifdef __MACH__ 21 #include <CoreServices/CoreServices.h> 22 #include <mach/mach.h> 23 #include <mach/mach_time.h> 24 #endif /* __MACH__ */ 25 26 #include "os.h" 27 #include "common.h" 28 29 #ifdef WPA_TRACE 30 31 #include "wpa_debug.h" 32 #include "trace.h" 33 #include "list.h" 34 35 static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list); 36 37 #define ALLOC_MAGIC 0xa84ef1b2 38 #define FREED_MAGIC 0x67fd487a 39 40 struct os_alloc_trace { 41 unsigned int magic; 42 struct dl_list list; 43 size_t len; 44 WPA_TRACE_INFO 45 } __attribute__((aligned(16))); 46 47 #endif /* WPA_TRACE */ 48 49 50 void os_sleep(os_time_t sec, os_time_t usec) 51 { 52 if (sec) 53 sleep(sec); 54 if (usec) 55 usleep(usec); 56 } 57 58 59 int os_get_time(struct os_time *t) 60 { 61 int res; 62 struct timeval tv; 63 res = gettimeofday(&tv, NULL); 64 t->sec = tv.tv_sec; 65 t->usec = tv.tv_usec; 66 return res; 67 } 68 69 70 int os_get_reltime(struct os_reltime *t) 71 { 72 #ifndef __MACH__ 73 #if defined(CLOCK_BOOTTIME) 74 static clockid_t clock_id = CLOCK_BOOTTIME; 75 #elif defined(CLOCK_MONOTONIC) 76 static clockid_t clock_id = CLOCK_MONOTONIC; 77 #else 78 static clockid_t clock_id = CLOCK_REALTIME; 79 #endif 80 struct timespec ts; 81 int res; 82 83 while (1) { 84 res = clock_gettime(clock_id, &ts); 85 if (res == 0) { 86 t->sec = ts.tv_sec; 87 t->usec = ts.tv_nsec / 1000; 88 return 0; 89 } 90 switch (clock_id) { 91 #ifdef CLOCK_BOOTTIME 92 case CLOCK_BOOTTIME: 93 clock_id = CLOCK_MONOTONIC; 94 break; 95 #endif 96 #ifdef CLOCK_MONOTONIC 97 case CLOCK_MONOTONIC: 98 clock_id = CLOCK_REALTIME; 99 break; 100 #endif 101 case CLOCK_REALTIME: 102 return -1; 103 } 104 } 105 #else /* __MACH__ */ 106 uint64_t abstime, nano; 107 static mach_timebase_info_data_t info = { 0, 0 }; 108 109 if (!info.denom) { 110 if (mach_timebase_info(&info) != KERN_SUCCESS) 111 return -1; 112 } 113 114 abstime = mach_absolute_time(); 115 nano = (abstime * info.numer) / info.denom; 116 117 t->sec = nano / NSEC_PER_SEC; 118 t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC; 119 120 return 0; 121 #endif /* __MACH__ */ 122 } 123 124 125 int os_mktime(int year, int month, int day, int hour, int min, int sec, 126 os_time_t *t) 127 { 128 struct tm tm, *tm1; 129 time_t t_local, t1, t2; 130 os_time_t tz_offset; 131 132 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 133 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 134 sec > 60) 135 return -1; 136 137 memset(&tm, 0, sizeof(tm)); 138 tm.tm_year = year - 1900; 139 tm.tm_mon = month - 1; 140 tm.tm_mday = day; 141 tm.tm_hour = hour; 142 tm.tm_min = min; 143 tm.tm_sec = sec; 144 145 t_local = mktime(&tm); 146 147 /* figure out offset to UTC */ 148 tm1 = localtime(&t_local); 149 if (tm1) { 150 t1 = mktime(tm1); 151 tm1 = gmtime(&t_local); 152 if (tm1) { 153 t2 = mktime(tm1); 154 tz_offset = t2 - t1; 155 } else 156 tz_offset = 0; 157 } else 158 tz_offset = 0; 159 160 *t = (os_time_t) t_local - tz_offset; 161 return 0; 162 } 163 164 165 int os_gmtime(os_time_t t, struct os_tm *tm) 166 { 167 struct tm *tm2; 168 time_t t2 = t; 169 170 tm2 = gmtime(&t2); 171 if (tm2 == NULL) 172 return -1; 173 tm->sec = tm2->tm_sec; 174 tm->min = tm2->tm_min; 175 tm->hour = tm2->tm_hour; 176 tm->day = tm2->tm_mday; 177 tm->month = tm2->tm_mon + 1; 178 tm->year = tm2->tm_year + 1900; 179 return 0; 180 } 181 182 183 #ifdef __APPLE__ 184 #include <fcntl.h> 185 static int os_daemon(int nochdir, int noclose) 186 { 187 int devnull; 188 189 if (chdir("/") < 0) 190 return -1; 191 192 devnull = open("/dev/null", O_RDWR); 193 if (devnull < 0) 194 return -1; 195 196 if (dup2(devnull, STDIN_FILENO) < 0) { 197 close(devnull); 198 return -1; 199 } 200 201 if (dup2(devnull, STDOUT_FILENO) < 0) { 202 close(devnull); 203 return -1; 204 } 205 206 if (dup2(devnull, STDERR_FILENO) < 0) { 207 close(devnull); 208 return -1; 209 } 210 211 return 0; 212 } 213 #else /* __APPLE__ */ 214 #define os_daemon daemon 215 #endif /* __APPLE__ */ 216 217 218 int os_daemonize(const char *pid_file) 219 { 220 #if defined(__uClinux__) || defined(__sun__) 221 return -1; 222 #else /* defined(__uClinux__) || defined(__sun__) */ 223 if (os_daemon(0, 0)) { 224 perror("daemon"); 225 return -1; 226 } 227 228 if (pid_file) { 229 FILE *f = fopen(pid_file, "w"); 230 if (f) { 231 fprintf(f, "%u\n", getpid()); 232 fclose(f); 233 } 234 } 235 236 return -0; 237 #endif /* defined(__uClinux__) || defined(__sun__) */ 238 } 239 240 241 void os_daemonize_terminate(const char *pid_file) 242 { 243 if (pid_file) 244 unlink(pid_file); 245 } 246 247 248 int os_get_random(unsigned char *buf, size_t len) 249 { 250 FILE *f; 251 size_t rc; 252 253 if (TEST_FAIL()) 254 return -1; 255 256 f = fopen("/dev/urandom", "rb"); 257 if (f == NULL) { 258 printf("Could not open /dev/urandom.\n"); 259 return -1; 260 } 261 262 rc = fread(buf, 1, len, f); 263 fclose(f); 264 265 return rc != len ? -1 : 0; 266 } 267 268 269 unsigned long os_random(void) 270 { 271 return random(); 272 } 273 274 275 char * os_rel2abs_path(const char *rel_path) 276 { 277 char *buf = NULL, *cwd, *ret; 278 size_t len = 128, cwd_len, rel_len, ret_len; 279 int last_errno; 280 281 if (!rel_path) 282 return NULL; 283 284 if (rel_path[0] == '/') 285 return os_strdup(rel_path); 286 287 for (;;) { 288 buf = os_malloc(len); 289 if (buf == NULL) 290 return NULL; 291 cwd = getcwd(buf, len); 292 if (cwd == NULL) { 293 last_errno = errno; 294 os_free(buf); 295 if (last_errno != ERANGE) 296 return NULL; 297 len *= 2; 298 if (len > 2000) 299 return NULL; 300 } else { 301 buf[len - 1] = '\0'; 302 break; 303 } 304 } 305 306 cwd_len = os_strlen(cwd); 307 rel_len = os_strlen(rel_path); 308 ret_len = cwd_len + 1 + rel_len + 1; 309 ret = os_malloc(ret_len); 310 if (ret) { 311 os_memcpy(ret, cwd, cwd_len); 312 ret[cwd_len] = '/'; 313 os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 314 ret[ret_len - 1] = '\0'; 315 } 316 os_free(buf); 317 return ret; 318 } 319 320 321 int os_program_init(void) 322 { 323 #ifdef ANDROID 324 /* 325 * We ignore errors here since errors are normal if we 326 * are already running as non-root. 327 */ 328 #ifdef ANDROID_SETGROUPS_OVERRIDE 329 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE }; 330 #else /* ANDROID_SETGROUPS_OVERRIDE */ 331 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE }; 332 #endif /* ANDROID_SETGROUPS_OVERRIDE */ 333 struct __user_cap_header_struct header; 334 struct __user_cap_data_struct cap; 335 336 setgroups(ARRAY_SIZE(groups), groups); 337 338 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 339 340 setgid(AID_WIFI); 341 setuid(AID_WIFI); 342 343 header.version = _LINUX_CAPABILITY_VERSION; 344 header.pid = 0; 345 cap.effective = cap.permitted = 346 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); 347 cap.inheritable = 0; 348 capset(&header, &cap); 349 #endif /* ANDROID */ 350 351 return 0; 352 } 353 354 355 void os_program_deinit(void) 356 { 357 #ifdef WPA_TRACE 358 struct os_alloc_trace *a; 359 unsigned long total = 0; 360 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { 361 total += a->len; 362 if (a->magic != ALLOC_MAGIC) { 363 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " 364 "len %lu", 365 a, a->magic, (unsigned long) a->len); 366 continue; 367 } 368 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", 369 a, (unsigned long) a->len); 370 wpa_trace_dump("memleak", a); 371 } 372 if (total) 373 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", 374 (unsigned long) total); 375 wpa_trace_deinit(); 376 #endif /* WPA_TRACE */ 377 } 378 379 380 int os_setenv(const char *name, const char *value, int overwrite) 381 { 382 return setenv(name, value, overwrite); 383 } 384 385 386 int os_unsetenv(const char *name) 387 { 388 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ 389 defined(__OpenBSD__) 390 unsetenv(name); 391 return 0; 392 #else 393 return unsetenv(name); 394 #endif 395 } 396 397 398 char * os_readfile(const char *name, size_t *len) 399 { 400 FILE *f; 401 char *buf; 402 long pos; 403 404 f = fopen(name, "rb"); 405 if (f == NULL) 406 return NULL; 407 408 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) { 409 fclose(f); 410 return NULL; 411 } 412 *len = pos; 413 if (fseek(f, 0, SEEK_SET) < 0) { 414 fclose(f); 415 return NULL; 416 } 417 418 buf = os_malloc(*len); 419 if (buf == NULL) { 420 fclose(f); 421 return NULL; 422 } 423 424 if (fread(buf, 1, *len, f) != *len) { 425 fclose(f); 426 os_free(buf); 427 return NULL; 428 } 429 430 fclose(f); 431 432 return buf; 433 } 434 435 436 int os_file_exists(const char *fname) 437 { 438 FILE *f = fopen(fname, "rb"); 439 if (f == NULL) 440 return 0; 441 fclose(f); 442 return 1; 443 } 444 445 446 int os_fdatasync(FILE *stream) 447 { 448 if (!fflush(stream)) { 449 #ifdef __linux__ 450 return fdatasync(fileno(stream)); 451 #else /* !__linux__ */ 452 #ifdef F_FULLFSYNC 453 /* OS X does not implement fdatasync(). */ 454 return fcntl(fileno(stream), F_FULLFSYNC); 455 #else /* F_FULLFSYNC */ 456 return fsync(fileno(stream)); 457 #endif /* F_FULLFSYNC */ 458 #endif /* __linux__ */ 459 } 460 461 return -1; 462 } 463 464 465 #ifndef WPA_TRACE 466 void * os_zalloc(size_t size) 467 { 468 return calloc(1, size); 469 } 470 #endif /* WPA_TRACE */ 471 472 473 size_t os_strlcpy(char *dest, const char *src, size_t siz) 474 { 475 const char *s = src; 476 size_t left = siz; 477 478 if (left) { 479 /* Copy string up to the maximum size of the dest buffer */ 480 while (--left != 0) { 481 if ((*dest++ = *s++) == '\0') 482 break; 483 } 484 } 485 486 if (left == 0) { 487 /* Not enough room for the string; force NUL-termination */ 488 if (siz != 0) 489 *dest = '\0'; 490 while (*s++) 491 ; /* determine total src string length */ 492 } 493 494 return s - src - 1; 495 } 496 497 498 int os_memcmp_const(const void *a, const void *b, size_t len) 499 { 500 const u8 *aa = a; 501 const u8 *bb = b; 502 size_t i; 503 u8 res; 504 505 for (res = 0, i = 0; i < len; i++) 506 res |= aa[i] ^ bb[i]; 507 508 return res; 509 } 510 511 512 #ifdef WPA_TRACE 513 514 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) 515 char wpa_trace_fail_func[256] = { 0 }; 516 unsigned int wpa_trace_fail_after; 517 518 static int testing_fail_alloc(void) 519 { 520 const char *func[WPA_TRACE_LEN]; 521 size_t i, res, len; 522 char *pos, *next; 523 int match; 524 525 if (!wpa_trace_fail_after) 526 return 0; 527 528 res = wpa_trace_calling_func(func, WPA_TRACE_LEN); 529 i = 0; 530 if (i < res && os_strcmp(func[i], __func__) == 0) 531 i++; 532 if (i < res && os_strcmp(func[i], "os_malloc") == 0) 533 i++; 534 if (i < res && os_strcmp(func[i], "os_zalloc") == 0) 535 i++; 536 if (i < res && os_strcmp(func[i], "os_calloc") == 0) 537 i++; 538 if (i < res && os_strcmp(func[i], "os_realloc") == 0) 539 i++; 540 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0) 541 i++; 542 if (i < res && os_strcmp(func[i], "os_strdup") == 0) 543 i++; 544 545 pos = wpa_trace_fail_func; 546 547 match = 0; 548 while (i < res) { 549 int allow_skip = 1; 550 int maybe = 0; 551 552 if (*pos == '=') { 553 allow_skip = 0; 554 pos++; 555 } else if (*pos == '?') { 556 maybe = 1; 557 pos++; 558 } 559 next = os_strchr(pos, ';'); 560 if (next) 561 len = next - pos; 562 else 563 len = os_strlen(pos); 564 if (os_memcmp(pos, func[i], len) != 0) { 565 if (maybe && next) { 566 pos = next + 1; 567 continue; 568 } 569 if (allow_skip) { 570 i++; 571 continue; 572 } 573 return 0; 574 } 575 if (!next) { 576 match = 1; 577 break; 578 } 579 pos = next + 1; 580 i++; 581 } 582 if (!match) 583 return 0; 584 585 wpa_trace_fail_after--; 586 if (wpa_trace_fail_after == 0) { 587 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s", 588 wpa_trace_fail_func); 589 for (i = 0; i < res; i++) 590 wpa_printf(MSG_INFO, "backtrace[%d] = %s", 591 (int) i, func[i]); 592 return 1; 593 } 594 595 return 0; 596 } 597 598 599 char wpa_trace_test_fail_func[256] = { 0 }; 600 unsigned int wpa_trace_test_fail_after; 601 602 int testing_test_fail(void) 603 { 604 const char *func[WPA_TRACE_LEN]; 605 size_t i, res, len; 606 char *pos, *next; 607 int match; 608 609 if (!wpa_trace_test_fail_after) 610 return 0; 611 612 res = wpa_trace_calling_func(func, WPA_TRACE_LEN); 613 i = 0; 614 if (i < res && os_strcmp(func[i], __func__) == 0) 615 i++; 616 617 pos = wpa_trace_test_fail_func; 618 619 match = 0; 620 while (i < res) { 621 int allow_skip = 1; 622 int maybe = 0; 623 624 if (*pos == '=') { 625 allow_skip = 0; 626 pos++; 627 } else if (*pos == '?') { 628 maybe = 1; 629 pos++; 630 } 631 next = os_strchr(pos, ';'); 632 if (next) 633 len = next - pos; 634 else 635 len = os_strlen(pos); 636 if (os_memcmp(pos, func[i], len) != 0) { 637 if (maybe && next) { 638 pos = next + 1; 639 continue; 640 } 641 if (allow_skip) { 642 i++; 643 continue; 644 } 645 return 0; 646 } 647 if (!next) { 648 match = 1; 649 break; 650 } 651 pos = next + 1; 652 i++; 653 } 654 if (!match) 655 return 0; 656 657 wpa_trace_test_fail_after--; 658 if (wpa_trace_test_fail_after == 0) { 659 wpa_printf(MSG_INFO, "TESTING: fail at %s", 660 wpa_trace_test_fail_func); 661 for (i = 0; i < res; i++) 662 wpa_printf(MSG_INFO, "backtrace[%d] = %s", 663 (int) i, func[i]); 664 return 1; 665 } 666 667 return 0; 668 } 669 670 #else 671 672 static inline int testing_fail_alloc(void) 673 { 674 return 0; 675 } 676 #endif 677 678 void * os_malloc(size_t size) 679 { 680 struct os_alloc_trace *a; 681 682 if (testing_fail_alloc()) 683 return NULL; 684 685 a = malloc(sizeof(*a) + size); 686 if (a == NULL) 687 return NULL; 688 a->magic = ALLOC_MAGIC; 689 dl_list_add(&alloc_list, &a->list); 690 a->len = size; 691 wpa_trace_record(a); 692 return a + 1; 693 } 694 695 696 void * os_realloc(void *ptr, size_t size) 697 { 698 struct os_alloc_trace *a; 699 size_t copy_len; 700 void *n; 701 702 if (ptr == NULL) 703 return os_malloc(size); 704 705 a = (struct os_alloc_trace *) ptr - 1; 706 if (a->magic != ALLOC_MAGIC) { 707 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", 708 a, a->magic, 709 a->magic == FREED_MAGIC ? " (already freed)" : ""); 710 wpa_trace_show("Invalid os_realloc() call"); 711 abort(); 712 } 713 n = os_malloc(size); 714 if (n == NULL) 715 return NULL; 716 copy_len = a->len; 717 if (copy_len > size) 718 copy_len = size; 719 os_memcpy(n, a + 1, copy_len); 720 os_free(ptr); 721 return n; 722 } 723 724 725 void os_free(void *ptr) 726 { 727 struct os_alloc_trace *a; 728 729 if (ptr == NULL) 730 return; 731 a = (struct os_alloc_trace *) ptr - 1; 732 if (a->magic != ALLOC_MAGIC) { 733 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", 734 a, a->magic, 735 a->magic == FREED_MAGIC ? " (already freed)" : ""); 736 wpa_trace_show("Invalid os_free() call"); 737 abort(); 738 } 739 dl_list_del(&a->list); 740 a->magic = FREED_MAGIC; 741 742 wpa_trace_check_ref(ptr); 743 free(a); 744 } 745 746 747 void * os_zalloc(size_t size) 748 { 749 void *ptr = os_malloc(size); 750 if (ptr) 751 os_memset(ptr, 0, size); 752 return ptr; 753 } 754 755 756 char * os_strdup(const char *s) 757 { 758 size_t len; 759 char *d; 760 len = os_strlen(s); 761 d = os_malloc(len + 1); 762 if (d == NULL) 763 return NULL; 764 os_memcpy(d, s, len); 765 d[len] = '\0'; 766 return d; 767 } 768 769 #endif /* WPA_TRACE */ 770 771 772 int os_exec(const char *program, const char *arg, int wait_completion) 773 { 774 pid_t pid; 775 int pid_status; 776 777 pid = fork(); 778 if (pid < 0) { 779 perror("fork"); 780 return -1; 781 } 782 783 if (pid == 0) { 784 /* run the external command in the child process */ 785 const int MAX_ARG = 30; 786 char *_program, *_arg, *pos; 787 char *argv[MAX_ARG + 1]; 788 int i; 789 790 _program = os_strdup(program); 791 _arg = os_strdup(arg); 792 793 argv[0] = _program; 794 795 i = 1; 796 pos = _arg; 797 while (i < MAX_ARG && pos && *pos) { 798 while (*pos == ' ') 799 pos++; 800 if (*pos == '\0') 801 break; 802 argv[i++] = pos; 803 pos = os_strchr(pos, ' '); 804 if (pos) 805 *pos++ = '\0'; 806 } 807 argv[i] = NULL; 808 809 execv(program, argv); 810 perror("execv"); 811 os_free(_program); 812 os_free(_arg); 813 exit(0); 814 return -1; 815 } 816 817 if (wait_completion) { 818 /* wait for the child process to complete in the parent */ 819 waitpid(pid, &pid_status, 0); 820 } 821 822 return 0; 823 } 824