18dbcf02cSchristos /* 28dbcf02cSchristos * OS specific functions for UNIX/POSIX systems 3460bb4fcSchristos * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi> 48dbcf02cSchristos * 5e604d861Schristos * This software may be distributed under the terms of the BSD license. 6e604d861Schristos * See README for more details. 78dbcf02cSchristos */ 88dbcf02cSchristos 98dbcf02cSchristos #include "includes.h" 108dbcf02cSchristos 11111b9fd8Schristos #include <time.h> 123c260e60Schristos #include <sys/wait.h> 13111b9fd8Schristos 14111b9fd8Schristos #ifdef ANDROID 153c260e60Schristos #include <sys/capability.h> 163c260e60Schristos #include <sys/prctl.h> 17111b9fd8Schristos #include <private/android_filesystem_config.h> 18111b9fd8Schristos #endif /* ANDROID */ 19111b9fd8Schristos 20ecc36642Schristos #ifdef __MACH__ 21ecc36642Schristos #include <CoreServices/CoreServices.h> 22ecc36642Schristos #include <mach/mach.h> 23ecc36642Schristos #include <mach/mach_time.h> 24ecc36642Schristos #endif /* __MACH__ */ 25ecc36642Schristos 268dbcf02cSchristos #include "os.h" 273c260e60Schristos #include "common.h" 288dbcf02cSchristos 298dbcf02cSchristos #ifdef WPA_TRACE 308dbcf02cSchristos 318dbcf02cSchristos #include "wpa_debug.h" 328dbcf02cSchristos #include "trace.h" 33e604d861Schristos #include "list.h" 348dbcf02cSchristos 35299bbf24Schristos static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list); 368dbcf02cSchristos 378dbcf02cSchristos #define ALLOC_MAGIC 0xa84ef1b2 388dbcf02cSchristos #define FREED_MAGIC 0x67fd487a 398dbcf02cSchristos 408dbcf02cSchristos struct os_alloc_trace { 418dbcf02cSchristos unsigned int magic; 42*45d3cc13Schristos struct dl_list list __attribute__((aligned(16))); 438dbcf02cSchristos size_t len; 448dbcf02cSchristos WPA_TRACE_INFO 45ecc36642Schristos } __attribute__((aligned(16))); 468dbcf02cSchristos 478dbcf02cSchristos #endif /* WPA_TRACE */ 488dbcf02cSchristos 498dbcf02cSchristos 508dbcf02cSchristos void os_sleep(os_time_t sec, os_time_t usec) 518dbcf02cSchristos { 52*45d3cc13Schristos #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L) 53*45d3cc13Schristos const struct timespec req = { sec, usec * 1000 }; 54*45d3cc13Schristos 55*45d3cc13Schristos nanosleep(&req, NULL); 56*45d3cc13Schristos #else 578dbcf02cSchristos if (sec) 588dbcf02cSchristos sleep(sec); 598dbcf02cSchristos if (usec) 608dbcf02cSchristos usleep(usec); 61*45d3cc13Schristos #endif 628dbcf02cSchristos } 638dbcf02cSchristos 648dbcf02cSchristos 658dbcf02cSchristos int os_get_time(struct os_time *t) 668dbcf02cSchristos { 678dbcf02cSchristos int res; 688dbcf02cSchristos struct timeval tv; 698dbcf02cSchristos res = gettimeofday(&tv, NULL); 708dbcf02cSchristos t->sec = tv.tv_sec; 718dbcf02cSchristos t->usec = tv.tv_usec; 728dbcf02cSchristos return res; 738dbcf02cSchristos } 748dbcf02cSchristos 758dbcf02cSchristos 763c260e60Schristos int os_get_reltime(struct os_reltime *t) 773c260e60Schristos { 78ecc36642Schristos #ifndef __MACH__ 793c260e60Schristos #if defined(CLOCK_BOOTTIME) 803c260e60Schristos static clockid_t clock_id = CLOCK_BOOTTIME; 813c260e60Schristos #elif defined(CLOCK_MONOTONIC) 823c260e60Schristos static clockid_t clock_id = CLOCK_MONOTONIC; 833c260e60Schristos #else 843c260e60Schristos static clockid_t clock_id = CLOCK_REALTIME; 853c260e60Schristos #endif 863c260e60Schristos struct timespec ts; 873c260e60Schristos int res; 883c260e60Schristos 89be6b3c4dSchristos if (TEST_FAIL()) 90be6b3c4dSchristos return -1; 91be6b3c4dSchristos 923c260e60Schristos while (1) { 933c260e60Schristos res = clock_gettime(clock_id, &ts); 943c260e60Schristos if (res == 0) { 953c260e60Schristos t->sec = ts.tv_sec; 963c260e60Schristos t->usec = ts.tv_nsec / 1000; 973c260e60Schristos return 0; 983c260e60Schristos } 993c260e60Schristos switch (clock_id) { 1003c260e60Schristos #ifdef CLOCK_BOOTTIME 1013c260e60Schristos case CLOCK_BOOTTIME: 1023c260e60Schristos clock_id = CLOCK_MONOTONIC; 1033c260e60Schristos break; 1043c260e60Schristos #endif 1053c260e60Schristos #ifdef CLOCK_MONOTONIC 1063c260e60Schristos case CLOCK_MONOTONIC: 1073c260e60Schristos clock_id = CLOCK_REALTIME; 1083c260e60Schristos break; 1093c260e60Schristos #endif 1103c260e60Schristos case CLOCK_REALTIME: 1113c260e60Schristos return -1; 1123c260e60Schristos } 1133c260e60Schristos } 114ecc36642Schristos #else /* __MACH__ */ 115ecc36642Schristos uint64_t abstime, nano; 116ecc36642Schristos static mach_timebase_info_data_t info = { 0, 0 }; 117ecc36642Schristos 118ecc36642Schristos if (!info.denom) { 119ecc36642Schristos if (mach_timebase_info(&info) != KERN_SUCCESS) 120ecc36642Schristos return -1; 121ecc36642Schristos } 122ecc36642Schristos 123ecc36642Schristos abstime = mach_absolute_time(); 124ecc36642Schristos nano = (abstime * info.numer) / info.denom; 125ecc36642Schristos 126ecc36642Schristos t->sec = nano / NSEC_PER_SEC; 127ecc36642Schristos t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC; 128ecc36642Schristos 129ecc36642Schristos return 0; 130ecc36642Schristos #endif /* __MACH__ */ 1313c260e60Schristos } 1323c260e60Schristos 1333c260e60Schristos 1348dbcf02cSchristos int os_mktime(int year, int month, int day, int hour, int min, int sec, 1358dbcf02cSchristos os_time_t *t) 1368dbcf02cSchristos { 1378dbcf02cSchristos struct tm tm, *tm1; 1388dbcf02cSchristos time_t t_local, t1, t2; 1398dbcf02cSchristos os_time_t tz_offset; 1408dbcf02cSchristos 1418dbcf02cSchristos if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 || 1428dbcf02cSchristos hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || 1438dbcf02cSchristos sec > 60) 1448dbcf02cSchristos return -1; 1458dbcf02cSchristos 1468dbcf02cSchristos memset(&tm, 0, sizeof(tm)); 1478dbcf02cSchristos tm.tm_year = year - 1900; 1488dbcf02cSchristos tm.tm_mon = month - 1; 1498dbcf02cSchristos tm.tm_mday = day; 1508dbcf02cSchristos tm.tm_hour = hour; 1518dbcf02cSchristos tm.tm_min = min; 1528dbcf02cSchristos tm.tm_sec = sec; 1538dbcf02cSchristos 1548dbcf02cSchristos t_local = mktime(&tm); 1558dbcf02cSchristos 1568dbcf02cSchristos /* figure out offset to UTC */ 1578dbcf02cSchristos tm1 = localtime(&t_local); 1588dbcf02cSchristos if (tm1) { 1598dbcf02cSchristos t1 = mktime(tm1); 1608dbcf02cSchristos tm1 = gmtime(&t_local); 1618dbcf02cSchristos if (tm1) { 1628dbcf02cSchristos t2 = mktime(tm1); 1638dbcf02cSchristos tz_offset = t2 - t1; 1648dbcf02cSchristos } else 1658dbcf02cSchristos tz_offset = 0; 1668dbcf02cSchristos } else 1678dbcf02cSchristos tz_offset = 0; 1688dbcf02cSchristos 1698dbcf02cSchristos *t = (os_time_t) t_local - tz_offset; 1708dbcf02cSchristos return 0; 1718dbcf02cSchristos } 1728dbcf02cSchristos 1738dbcf02cSchristos 174111b9fd8Schristos int os_gmtime(os_time_t t, struct os_tm *tm) 175111b9fd8Schristos { 176111b9fd8Schristos struct tm *tm2; 177111b9fd8Schristos time_t t2 = t; 178111b9fd8Schristos 179111b9fd8Schristos tm2 = gmtime(&t2); 180111b9fd8Schristos if (tm2 == NULL) 181111b9fd8Schristos return -1; 182111b9fd8Schristos tm->sec = tm2->tm_sec; 183111b9fd8Schristos tm->min = tm2->tm_min; 184111b9fd8Schristos tm->hour = tm2->tm_hour; 185111b9fd8Schristos tm->day = tm2->tm_mday; 186111b9fd8Schristos tm->month = tm2->tm_mon + 1; 187111b9fd8Schristos tm->year = tm2->tm_year + 1900; 188111b9fd8Schristos return 0; 189111b9fd8Schristos } 190111b9fd8Schristos 191111b9fd8Schristos 1928dbcf02cSchristos #ifdef __APPLE__ 1938dbcf02cSchristos #include <fcntl.h> 1948dbcf02cSchristos static int os_daemon(int nochdir, int noclose) 1958dbcf02cSchristos { 1968dbcf02cSchristos int devnull; 1978dbcf02cSchristos 1988dbcf02cSchristos if (chdir("/") < 0) 1998dbcf02cSchristos return -1; 2008dbcf02cSchristos 2018dbcf02cSchristos devnull = open("/dev/null", O_RDWR); 2028dbcf02cSchristos if (devnull < 0) 2038dbcf02cSchristos return -1; 2048dbcf02cSchristos 2058dbcf02cSchristos if (dup2(devnull, STDIN_FILENO) < 0) { 2068dbcf02cSchristos close(devnull); 2078dbcf02cSchristos return -1; 2088dbcf02cSchristos } 2098dbcf02cSchristos 2108dbcf02cSchristos if (dup2(devnull, STDOUT_FILENO) < 0) { 2118dbcf02cSchristos close(devnull); 2128dbcf02cSchristos return -1; 2138dbcf02cSchristos } 2148dbcf02cSchristos 2158dbcf02cSchristos if (dup2(devnull, STDERR_FILENO) < 0) { 2168dbcf02cSchristos close(devnull); 2178dbcf02cSchristos return -1; 2188dbcf02cSchristos } 2198dbcf02cSchristos 2208dbcf02cSchristos return 0; 2218dbcf02cSchristos } 2228dbcf02cSchristos #else /* __APPLE__ */ 2238dbcf02cSchristos #define os_daemon daemon 2248dbcf02cSchristos #endif /* __APPLE__ */ 2258dbcf02cSchristos 2268dbcf02cSchristos 2278dbcf02cSchristos int os_daemonize(const char *pid_file) 2288dbcf02cSchristos { 229111b9fd8Schristos #if defined(__uClinux__) || defined(__sun__) 2308dbcf02cSchristos return -1; 231111b9fd8Schristos #else /* defined(__uClinux__) || defined(__sun__) */ 2328dbcf02cSchristos if (os_daemon(0, 0)) { 2338dbcf02cSchristos perror("daemon"); 2348dbcf02cSchristos return -1; 2358dbcf02cSchristos } 2368dbcf02cSchristos 2378dbcf02cSchristos if (pid_file) { 2388dbcf02cSchristos FILE *f = fopen(pid_file, "w"); 2398dbcf02cSchristos if (f) { 2408dbcf02cSchristos fprintf(f, "%u\n", getpid()); 2418dbcf02cSchristos fclose(f); 2428dbcf02cSchristos } 2438dbcf02cSchristos } 2448dbcf02cSchristos 2458dbcf02cSchristos return -0; 246111b9fd8Schristos #endif /* defined(__uClinux__) || defined(__sun__) */ 2478dbcf02cSchristos } 2488dbcf02cSchristos 2498dbcf02cSchristos 2508dbcf02cSchristos void os_daemonize_terminate(const char *pid_file) 2518dbcf02cSchristos { 2528dbcf02cSchristos if (pid_file) 2538dbcf02cSchristos unlink(pid_file); 2548dbcf02cSchristos } 2558dbcf02cSchristos 2568dbcf02cSchristos 2578dbcf02cSchristos int os_get_random(unsigned char *buf, size_t len) 2588dbcf02cSchristos { 259460bb4fcSchristos #ifdef TEST_FUZZ 260460bb4fcSchristos size_t i; 261460bb4fcSchristos 262460bb4fcSchristos for (i = 0; i < len; i++) 263460bb4fcSchristos buf[i] = i & 0xff; 264460bb4fcSchristos return 0; 265460bb4fcSchristos #else /* TEST_FUZZ */ 2668dbcf02cSchristos FILE *f; 2678dbcf02cSchristos size_t rc; 2688dbcf02cSchristos 269ecc36642Schristos if (TEST_FAIL()) 270ecc36642Schristos return -1; 271ecc36642Schristos 2728dbcf02cSchristos f = fopen("/dev/urandom", "rb"); 2738dbcf02cSchristos if (f == NULL) { 2748dbcf02cSchristos printf("Could not open /dev/urandom.\n"); 2758dbcf02cSchristos return -1; 2768dbcf02cSchristos } 2778dbcf02cSchristos 2788dbcf02cSchristos rc = fread(buf, 1, len, f); 2798dbcf02cSchristos fclose(f); 2808dbcf02cSchristos 2818dbcf02cSchristos return rc != len ? -1 : 0; 282460bb4fcSchristos #endif /* TEST_FUZZ */ 2838dbcf02cSchristos } 2848dbcf02cSchristos 2858dbcf02cSchristos 2868dbcf02cSchristos unsigned long os_random(void) 2878dbcf02cSchristos { 2888dbcf02cSchristos return random(); 2898dbcf02cSchristos } 2908dbcf02cSchristos 2918dbcf02cSchristos 2928dbcf02cSchristos char * os_rel2abs_path(const char *rel_path) 2938dbcf02cSchristos { 2948dbcf02cSchristos char *buf = NULL, *cwd, *ret; 2958dbcf02cSchristos size_t len = 128, cwd_len, rel_len, ret_len; 2968dbcf02cSchristos int last_errno; 2978dbcf02cSchristos 2983c260e60Schristos if (!rel_path) 2993c260e60Schristos return NULL; 3003c260e60Schristos 3018dbcf02cSchristos if (rel_path[0] == '/') 3028dbcf02cSchristos return os_strdup(rel_path); 3038dbcf02cSchristos 3048dbcf02cSchristos for (;;) { 3058dbcf02cSchristos buf = os_malloc(len); 3068dbcf02cSchristos if (buf == NULL) 3078dbcf02cSchristos return NULL; 3088dbcf02cSchristos cwd = getcwd(buf, len); 3098dbcf02cSchristos if (cwd == NULL) { 3108dbcf02cSchristos last_errno = errno; 3118dbcf02cSchristos os_free(buf); 3128dbcf02cSchristos if (last_errno != ERANGE) 3138dbcf02cSchristos return NULL; 3148dbcf02cSchristos len *= 2; 3158dbcf02cSchristos if (len > 2000) 3168dbcf02cSchristos return NULL; 3178dbcf02cSchristos } else { 3188dbcf02cSchristos buf[len - 1] = '\0'; 3198dbcf02cSchristos break; 3208dbcf02cSchristos } 3218dbcf02cSchristos } 3228dbcf02cSchristos 3238dbcf02cSchristos cwd_len = os_strlen(cwd); 3248dbcf02cSchristos rel_len = os_strlen(rel_path); 3258dbcf02cSchristos ret_len = cwd_len + 1 + rel_len + 1; 3268dbcf02cSchristos ret = os_malloc(ret_len); 3278dbcf02cSchristos if (ret) { 3288dbcf02cSchristos os_memcpy(ret, cwd, cwd_len); 3298dbcf02cSchristos ret[cwd_len] = '/'; 3308dbcf02cSchristos os_memcpy(ret + cwd_len + 1, rel_path, rel_len); 3318dbcf02cSchristos ret[ret_len - 1] = '\0'; 3328dbcf02cSchristos } 3338dbcf02cSchristos os_free(buf); 3348dbcf02cSchristos return ret; 3358dbcf02cSchristos } 3368dbcf02cSchristos 3378dbcf02cSchristos 3388dbcf02cSchristos int os_program_init(void) 3398dbcf02cSchristos { 340*45d3cc13Schristos unsigned int seed; 341*45d3cc13Schristos 342111b9fd8Schristos #ifdef ANDROID 343111b9fd8Schristos /* 344111b9fd8Schristos * We ignore errors here since errors are normal if we 345111b9fd8Schristos * are already running as non-root. 346111b9fd8Schristos */ 3473c260e60Schristos #ifdef ANDROID_SETGROUPS_OVERRIDE 3483c260e60Schristos gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE }; 3493c260e60Schristos #else /* ANDROID_SETGROUPS_OVERRIDE */ 350111b9fd8Schristos gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE }; 3513c260e60Schristos #endif /* ANDROID_SETGROUPS_OVERRIDE */ 352111b9fd8Schristos struct __user_cap_header_struct header; 353111b9fd8Schristos struct __user_cap_data_struct cap; 354111b9fd8Schristos 3553c260e60Schristos setgroups(ARRAY_SIZE(groups), groups); 356111b9fd8Schristos 357111b9fd8Schristos prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 358111b9fd8Schristos 359111b9fd8Schristos setgid(AID_WIFI); 360111b9fd8Schristos setuid(AID_WIFI); 361111b9fd8Schristos 362111b9fd8Schristos header.version = _LINUX_CAPABILITY_VERSION; 363111b9fd8Schristos header.pid = 0; 364111b9fd8Schristos cap.effective = cap.permitted = 365111b9fd8Schristos (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW); 366111b9fd8Schristos cap.inheritable = 0; 367111b9fd8Schristos capset(&header, &cap); 368111b9fd8Schristos #endif /* ANDROID */ 369111b9fd8Schristos 370*45d3cc13Schristos if (os_get_random((unsigned char *) &seed, sizeof(seed)) == 0) 371*45d3cc13Schristos srandom(seed); 372*45d3cc13Schristos 3738dbcf02cSchristos return 0; 3748dbcf02cSchristos } 3758dbcf02cSchristos 3768dbcf02cSchristos 3778dbcf02cSchristos void os_program_deinit(void) 3788dbcf02cSchristos { 3798dbcf02cSchristos #ifdef WPA_TRACE 3808dbcf02cSchristos struct os_alloc_trace *a; 3818dbcf02cSchristos unsigned long total = 0; 3828dbcf02cSchristos dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) { 3838dbcf02cSchristos total += a->len; 3848dbcf02cSchristos if (a->magic != ALLOC_MAGIC) { 3858dbcf02cSchristos wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x " 3868dbcf02cSchristos "len %lu", 3878dbcf02cSchristos a, a->magic, (unsigned long) a->len); 3888dbcf02cSchristos continue; 3898dbcf02cSchristos } 3908dbcf02cSchristos wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu", 3918dbcf02cSchristos a, (unsigned long) a->len); 3928dbcf02cSchristos wpa_trace_dump("memleak", a); 3938dbcf02cSchristos } 3948dbcf02cSchristos if (total) 3958dbcf02cSchristos wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes", 3968dbcf02cSchristos (unsigned long) total); 397ecc36642Schristos wpa_trace_deinit(); 3988dbcf02cSchristos #endif /* WPA_TRACE */ 3998dbcf02cSchristos } 4008dbcf02cSchristos 4018dbcf02cSchristos 4028dbcf02cSchristos int os_setenv(const char *name, const char *value, int overwrite) 4038dbcf02cSchristos { 4048dbcf02cSchristos return setenv(name, value, overwrite); 4058dbcf02cSchristos } 4068dbcf02cSchristos 4078dbcf02cSchristos 4088dbcf02cSchristos int os_unsetenv(const char *name) 4098dbcf02cSchristos { 4108dbcf02cSchristos #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \ 4118dbcf02cSchristos defined(__OpenBSD__) 4128dbcf02cSchristos unsetenv(name); 4138dbcf02cSchristos return 0; 4148dbcf02cSchristos #else 4158dbcf02cSchristos return unsetenv(name); 4168dbcf02cSchristos #endif 4178dbcf02cSchristos } 4188dbcf02cSchristos 4198dbcf02cSchristos 4208dbcf02cSchristos char * os_readfile(const char *name, size_t *len) 4218dbcf02cSchristos { 4228dbcf02cSchristos FILE *f; 4238dbcf02cSchristos char *buf; 424111b9fd8Schristos long pos; 4258dbcf02cSchristos 4268dbcf02cSchristos f = fopen(name, "rb"); 4278dbcf02cSchristos if (f == NULL) 4288dbcf02cSchristos return NULL; 4298dbcf02cSchristos 430111b9fd8Schristos if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) { 431111b9fd8Schristos fclose(f); 432111b9fd8Schristos return NULL; 433111b9fd8Schristos } 434111b9fd8Schristos *len = pos; 435111b9fd8Schristos if (fseek(f, 0, SEEK_SET) < 0) { 436111b9fd8Schristos fclose(f); 437111b9fd8Schristos return NULL; 438111b9fd8Schristos } 4398dbcf02cSchristos 4408dbcf02cSchristos buf = os_malloc(*len); 4418dbcf02cSchristos if (buf == NULL) { 4428dbcf02cSchristos fclose(f); 4438dbcf02cSchristos return NULL; 4448dbcf02cSchristos } 4458dbcf02cSchristos 4468dbcf02cSchristos if (fread(buf, 1, *len, f) != *len) { 4478dbcf02cSchristos fclose(f); 4488dbcf02cSchristos os_free(buf); 4498dbcf02cSchristos return NULL; 4508dbcf02cSchristos } 4518dbcf02cSchristos 4528dbcf02cSchristos fclose(f); 4538dbcf02cSchristos 4548dbcf02cSchristos return buf; 4558dbcf02cSchristos } 4568dbcf02cSchristos 4578dbcf02cSchristos 4583c260e60Schristos int os_file_exists(const char *fname) 4593c260e60Schristos { 460ecc36642Schristos return access(fname, F_OK) == 0; 461ecc36642Schristos } 462ecc36642Schristos 463ecc36642Schristos 464ecc36642Schristos int os_fdatasync(FILE *stream) 465ecc36642Schristos { 466ecc36642Schristos if (!fflush(stream)) { 467*45d3cc13Schristos #if defined __FreeBSD__ || defined __linux__ 468ecc36642Schristos return fdatasync(fileno(stream)); 469*45d3cc13Schristos #else /* !__linux__ && !__FreeBSD__ */ 470ecc36642Schristos #ifdef F_FULLFSYNC 471ecc36642Schristos /* OS X does not implement fdatasync(). */ 472ecc36642Schristos return fcntl(fileno(stream), F_FULLFSYNC); 473ecc36642Schristos #else /* F_FULLFSYNC */ 474ecc36642Schristos return fsync(fileno(stream)); 475ecc36642Schristos #endif /* F_FULLFSYNC */ 476ecc36642Schristos #endif /* __linux__ */ 477ecc36642Schristos } 478ecc36642Schristos 479ecc36642Schristos return -1; 4803c260e60Schristos } 4813c260e60Schristos 4823c260e60Schristos 4838dbcf02cSchristos #ifndef WPA_TRACE 4848dbcf02cSchristos void * os_zalloc(size_t size) 4858dbcf02cSchristos { 4868dbcf02cSchristos return calloc(1, size); 4878dbcf02cSchristos } 4888dbcf02cSchristos #endif /* WPA_TRACE */ 4898dbcf02cSchristos 4908dbcf02cSchristos 4918dbcf02cSchristos size_t os_strlcpy(char *dest, const char *src, size_t siz) 4928dbcf02cSchristos { 4938dbcf02cSchristos const char *s = src; 4948dbcf02cSchristos size_t left = siz; 4958dbcf02cSchristos 4968dbcf02cSchristos if (left) { 4978dbcf02cSchristos /* Copy string up to the maximum size of the dest buffer */ 4988dbcf02cSchristos while (--left != 0) { 4998dbcf02cSchristos if ((*dest++ = *s++) == '\0') 5008dbcf02cSchristos break; 5018dbcf02cSchristos } 5028dbcf02cSchristos } 5038dbcf02cSchristos 5048dbcf02cSchristos if (left == 0) { 5058dbcf02cSchristos /* Not enough room for the string; force NUL-termination */ 5068dbcf02cSchristos if (siz != 0) 5078dbcf02cSchristos *dest = '\0'; 5088dbcf02cSchristos while (*s++) 5098dbcf02cSchristos ; /* determine total src string length */ 5108dbcf02cSchristos } 5118dbcf02cSchristos 5128dbcf02cSchristos return s - src - 1; 5138dbcf02cSchristos } 5148dbcf02cSchristos 5158dbcf02cSchristos 5163c260e60Schristos int os_memcmp_const(const void *a, const void *b, size_t len) 5173c260e60Schristos { 5183c260e60Schristos const u8 *aa = a; 5193c260e60Schristos const u8 *bb = b; 5203c260e60Schristos size_t i; 5213c260e60Schristos u8 res; 5223c260e60Schristos 5233c260e60Schristos for (res = 0, i = 0; i < len; i++) 5243c260e60Schristos res |= aa[i] ^ bb[i]; 5253c260e60Schristos 5263c260e60Schristos return res; 5273c260e60Schristos } 5283c260e60Schristos 5293c260e60Schristos 530be6b3c4dSchristos void * os_memdup(const void *src, size_t len) 531be6b3c4dSchristos { 532be6b3c4dSchristos void *r = os_malloc(len); 533be6b3c4dSchristos 534460bb4fcSchristos if (r && src) 535be6b3c4dSchristos os_memcpy(r, src, len); 536be6b3c4dSchristos return r; 537be6b3c4dSchristos } 538be6b3c4dSchristos 539be6b3c4dSchristos 5408dbcf02cSchristos #ifdef WPA_TRACE 5418dbcf02cSchristos 542299bbf24Schristos #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) 543*45d3cc13Schristos struct wpa_trace_test_fail { 544*45d3cc13Schristos unsigned int fail_after; 545*45d3cc13Schristos char pattern[256]; 546*45d3cc13Schristos } wpa_trace_test_fail[5][2]; 547299bbf24Schristos 548*45d3cc13Schristos int testing_test_fail(const char *tag, bool is_alloc) 549299bbf24Schristos { 550*45d3cc13Schristos const char *ignore_list[] = { 551*45d3cc13Schristos "os_malloc", "os_zalloc", "os_calloc", "os_realloc", 552*45d3cc13Schristos "os_realloc_array", "os_strdup", "os_memdup" 553*45d3cc13Schristos }; 554299bbf24Schristos const char *func[WPA_TRACE_LEN]; 555*45d3cc13Schristos size_t i, j, res, len, idx; 556299bbf24Schristos char *pos, *next; 557299bbf24Schristos int match; 558299bbf24Schristos 559*45d3cc13Schristos is_alloc = !!is_alloc; 560*45d3cc13Schristos 561*45d3cc13Schristos for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) { 562*45d3cc13Schristos if (wpa_trace_test_fail[is_alloc][idx].fail_after != 0) 563*45d3cc13Schristos break; 564*45d3cc13Schristos } 565*45d3cc13Schristos if (idx >= ARRAY_SIZE(wpa_trace_test_fail[is_alloc])) 566299bbf24Schristos return 0; 567299bbf24Schristos 568299bbf24Schristos res = wpa_trace_calling_func(func, WPA_TRACE_LEN); 569299bbf24Schristos i = 0; 570*45d3cc13Schristos 571*45d3cc13Schristos if (is_alloc) { 572*45d3cc13Schristos /* Skip our own stack frame */ 573be6b3c4dSchristos i++; 574299bbf24Schristos 575*45d3cc13Schristos /* Skip allocation helpers */ 576*45d3cc13Schristos for (j = 0; j < ARRAY_SIZE(ignore_list) && i < res; j++) { 577*45d3cc13Schristos if (os_strcmp(func[i], ignore_list[j]) == 0) 578*45d3cc13Schristos i++; 579*45d3cc13Schristos } 580*45d3cc13Schristos } else { 581*45d3cc13Schristos /* Not allocation, we might have a tag, if so, replace our 582*45d3cc13Schristos * own stack frame with the tag, otherwise skip it. 583*45d3cc13Schristos */ 584*45d3cc13Schristos if (tag) 585*45d3cc13Schristos func[0] = tag; 586*45d3cc13Schristos else 587*45d3cc13Schristos i++; 588*45d3cc13Schristos } 589*45d3cc13Schristos 590*45d3cc13Schristos pos = wpa_trace_test_fail[is_alloc][idx].pattern; 591*45d3cc13Schristos 592*45d3cc13Schristos /* The prefixes mean: 593*45d3cc13Schristos * - '=': The function needs to be next in the backtrace 594*45d3cc13Schristos * - '?': The function is optionally present in the backtrace 595*45d3cc13Schristos */ 596299bbf24Schristos 597299bbf24Schristos match = 0; 598299bbf24Schristos while (i < res) { 599299bbf24Schristos int allow_skip = 1; 600299bbf24Schristos int maybe = 0; 601*45d3cc13Schristos bool prefix = false; 602299bbf24Schristos 603299bbf24Schristos if (*pos == '=') { 604299bbf24Schristos allow_skip = 0; 605299bbf24Schristos pos++; 606299bbf24Schristos } else if (*pos == '?') { 607299bbf24Schristos maybe = 1; 608299bbf24Schristos pos++; 609299bbf24Schristos } 610299bbf24Schristos next = os_strchr(pos, ';'); 611299bbf24Schristos if (next) 612299bbf24Schristos len = next - pos; 613299bbf24Schristos else 614299bbf24Schristos len = os_strlen(pos); 615*45d3cc13Schristos if (len >= 1 && pos[len - 1] == '*') { 616*45d3cc13Schristos prefix = true; 617*45d3cc13Schristos len -= 1; 618*45d3cc13Schristos } 619*45d3cc13Schristos if (os_strncmp(pos, func[i], len) != 0 || 620*45d3cc13Schristos (!prefix && func[i][len] != '\0')) { 621299bbf24Schristos if (maybe && next) { 622299bbf24Schristos pos = next + 1; 623299bbf24Schristos continue; 624299bbf24Schristos } 625299bbf24Schristos if (allow_skip) { 626299bbf24Schristos i++; 627299bbf24Schristos continue; 628299bbf24Schristos } 629299bbf24Schristos return 0; 630299bbf24Schristos } 631299bbf24Schristos if (!next) { 632299bbf24Schristos match = 1; 633299bbf24Schristos break; 634299bbf24Schristos } 635299bbf24Schristos pos = next + 1; 636299bbf24Schristos i++; 637299bbf24Schristos } 638299bbf24Schristos if (!match) 639299bbf24Schristos return 0; 640299bbf24Schristos 641*45d3cc13Schristos wpa_trace_test_fail[is_alloc][idx].fail_after--; 642*45d3cc13Schristos if (wpa_trace_test_fail[is_alloc][idx].fail_after == 0) { 643ecc36642Schristos wpa_printf(MSG_INFO, "TESTING: fail at %s", 644*45d3cc13Schristos wpa_trace_test_fail[is_alloc][idx].pattern); 645ecc36642Schristos for (i = 0; i < res; i++) 646ecc36642Schristos wpa_printf(MSG_INFO, "backtrace[%d] = %s", 647ecc36642Schristos (int) i, func[i]); 648ecc36642Schristos return 1; 649ecc36642Schristos } 650ecc36642Schristos 651ecc36642Schristos return 0; 652ecc36642Schristos } 653ecc36642Schristos 654299bbf24Schristos 655*45d3cc13Schristos int testing_set_fail_pattern(bool is_alloc, char *patterns) 656*45d3cc13Schristos { 657*45d3cc13Schristos #ifdef WPA_TRACE_BFD 658*45d3cc13Schristos char *token, *context = NULL; 659*45d3cc13Schristos size_t idx; 660*45d3cc13Schristos 661*45d3cc13Schristos is_alloc = !!is_alloc; 662*45d3cc13Schristos 663*45d3cc13Schristos os_memset(wpa_trace_test_fail[is_alloc], 0, 664*45d3cc13Schristos sizeof(wpa_trace_test_fail[is_alloc])); 665*45d3cc13Schristos 666*45d3cc13Schristos idx = 0; 667*45d3cc13Schristos while ((token = str_token(patterns, " \n\r\t", &context)) && 668*45d3cc13Schristos idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc])) { 669*45d3cc13Schristos wpa_trace_test_fail[is_alloc][idx].fail_after = atoi(token); 670*45d3cc13Schristos token = os_strchr(token, ':'); 671*45d3cc13Schristos if (!token) { 672*45d3cc13Schristos os_memset(wpa_trace_test_fail[is_alloc], 0, 673*45d3cc13Schristos sizeof(wpa_trace_test_fail[is_alloc])); 674*45d3cc13Schristos return -1; 675*45d3cc13Schristos } 676*45d3cc13Schristos 677*45d3cc13Schristos os_strlcpy(wpa_trace_test_fail[is_alloc][idx].pattern, 678*45d3cc13Schristos token + 1, 679*45d3cc13Schristos sizeof(wpa_trace_test_fail[is_alloc][0].pattern)); 680*45d3cc13Schristos idx++; 681*45d3cc13Schristos } 682*45d3cc13Schristos 683*45d3cc13Schristos return 0; 684*45d3cc13Schristos #else /* WPA_TRACE_BFD */ 685*45d3cc13Schristos return -1; 686*45d3cc13Schristos #endif /* WPA_TRACE_BFD */ 687*45d3cc13Schristos } 688*45d3cc13Schristos 689*45d3cc13Schristos 690*45d3cc13Schristos int testing_get_fail_pattern(bool is_alloc, char *buf, size_t buflen) 691*45d3cc13Schristos { 692*45d3cc13Schristos #ifdef WPA_TRACE_BFD 693*45d3cc13Schristos size_t idx, ret; 694*45d3cc13Schristos char *pos = buf; 695*45d3cc13Schristos char *end = buf + buflen; 696*45d3cc13Schristos 697*45d3cc13Schristos is_alloc = !!is_alloc; 698*45d3cc13Schristos 699*45d3cc13Schristos for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) { 700*45d3cc13Schristos if (wpa_trace_test_fail[is_alloc][idx].pattern[0] == '\0') 701*45d3cc13Schristos break; 702*45d3cc13Schristos 703*45d3cc13Schristos ret = os_snprintf(pos, end - pos, "%s%u:%s", 704*45d3cc13Schristos pos == buf ? "" : " ", 705*45d3cc13Schristos wpa_trace_test_fail[is_alloc][idx].fail_after, 706*45d3cc13Schristos wpa_trace_test_fail[is_alloc][idx].pattern); 707*45d3cc13Schristos if (os_snprintf_error(end - pos, ret)) 708*45d3cc13Schristos break; 709*45d3cc13Schristos pos += ret; 710*45d3cc13Schristos } 711*45d3cc13Schristos 712*45d3cc13Schristos return pos - buf; 713*45d3cc13Schristos #else /* WPA_TRACE_BFD */ 714*45d3cc13Schristos return -1; 715*45d3cc13Schristos #endif /* WPA_TRACE_BFD */ 716*45d3cc13Schristos } 717*45d3cc13Schristos 718*45d3cc13Schristos #else /* defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) */ 719*45d3cc13Schristos 720*45d3cc13Schristos static inline int testing_test_fail(const char *tag, bool is_alloc) 721299bbf24Schristos { 722299bbf24Schristos return 0; 723299bbf24Schristos } 724*45d3cc13Schristos 725299bbf24Schristos #endif 726299bbf24Schristos 7278dbcf02cSchristos void * os_malloc(size_t size) 7288dbcf02cSchristos { 7298dbcf02cSchristos struct os_alloc_trace *a; 730299bbf24Schristos 731*45d3cc13Schristos if (testing_test_fail(NULL, true)) 732299bbf24Schristos return NULL; 733299bbf24Schristos 7348dbcf02cSchristos a = malloc(sizeof(*a) + size); 7358dbcf02cSchristos if (a == NULL) 7368dbcf02cSchristos return NULL; 7378dbcf02cSchristos a->magic = ALLOC_MAGIC; 7388dbcf02cSchristos dl_list_add(&alloc_list, &a->list); 7398dbcf02cSchristos a->len = size; 7408dbcf02cSchristos wpa_trace_record(a); 7418dbcf02cSchristos return a + 1; 7428dbcf02cSchristos } 7438dbcf02cSchristos 7448dbcf02cSchristos 7458dbcf02cSchristos void * os_realloc(void *ptr, size_t size) 7468dbcf02cSchristos { 7478dbcf02cSchristos struct os_alloc_trace *a; 7488dbcf02cSchristos size_t copy_len; 7498dbcf02cSchristos void *n; 7508dbcf02cSchristos 7518dbcf02cSchristos if (ptr == NULL) 7528dbcf02cSchristos return os_malloc(size); 7538dbcf02cSchristos 754e6e4448bSchristos a = (struct os_alloc_trace *) ptr - 1; 7558dbcf02cSchristos if (a->magic != ALLOC_MAGIC) { 7568dbcf02cSchristos wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s", 7578dbcf02cSchristos a, a->magic, 7588dbcf02cSchristos a->magic == FREED_MAGIC ? " (already freed)" : ""); 7598dbcf02cSchristos wpa_trace_show("Invalid os_realloc() call"); 7608dbcf02cSchristos abort(); 7618dbcf02cSchristos } 7628dbcf02cSchristos n = os_malloc(size); 7638dbcf02cSchristos if (n == NULL) 7648dbcf02cSchristos return NULL; 7658dbcf02cSchristos copy_len = a->len; 7668dbcf02cSchristos if (copy_len > size) 7678dbcf02cSchristos copy_len = size; 7688dbcf02cSchristos os_memcpy(n, a + 1, copy_len); 7698dbcf02cSchristos os_free(ptr); 7708dbcf02cSchristos return n; 7718dbcf02cSchristos } 7728dbcf02cSchristos 7738dbcf02cSchristos 7748dbcf02cSchristos void os_free(void *ptr) 7758dbcf02cSchristos { 7768dbcf02cSchristos struct os_alloc_trace *a; 7778dbcf02cSchristos 7788dbcf02cSchristos if (ptr == NULL) 7798dbcf02cSchristos return; 780e6e4448bSchristos a = (struct os_alloc_trace *) ptr - 1; 7818dbcf02cSchristos if (a->magic != ALLOC_MAGIC) { 7828dbcf02cSchristos wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s", 7838dbcf02cSchristos a, a->magic, 7848dbcf02cSchristos a->magic == FREED_MAGIC ? " (already freed)" : ""); 7858dbcf02cSchristos wpa_trace_show("Invalid os_free() call"); 7868dbcf02cSchristos abort(); 7878dbcf02cSchristos } 7888dbcf02cSchristos dl_list_del(&a->list); 7898dbcf02cSchristos a->magic = FREED_MAGIC; 7908dbcf02cSchristos 7918dbcf02cSchristos wpa_trace_check_ref(ptr); 7928dbcf02cSchristos free(a); 7938dbcf02cSchristos } 7948dbcf02cSchristos 7958dbcf02cSchristos 7968dbcf02cSchristos void * os_zalloc(size_t size) 7978dbcf02cSchristos { 7988dbcf02cSchristos void *ptr = os_malloc(size); 7998dbcf02cSchristos if (ptr) 8008dbcf02cSchristos os_memset(ptr, 0, size); 8018dbcf02cSchristos return ptr; 8028dbcf02cSchristos } 8038dbcf02cSchristos 8048dbcf02cSchristos 8058dbcf02cSchristos char * os_strdup(const char *s) 8068dbcf02cSchristos { 8078dbcf02cSchristos size_t len; 8088dbcf02cSchristos char *d; 8098dbcf02cSchristos len = os_strlen(s); 8108dbcf02cSchristos d = os_malloc(len + 1); 8118dbcf02cSchristos if (d == NULL) 8128dbcf02cSchristos return NULL; 8138dbcf02cSchristos os_memcpy(d, s, len); 8148dbcf02cSchristos d[len] = '\0'; 8158dbcf02cSchristos return d; 8168dbcf02cSchristos } 8178dbcf02cSchristos 8188dbcf02cSchristos #endif /* WPA_TRACE */ 8193c260e60Schristos 8203c260e60Schristos 8213c260e60Schristos int os_exec(const char *program, const char *arg, int wait_completion) 8223c260e60Schristos { 8233c260e60Schristos pid_t pid; 8243c260e60Schristos int pid_status; 8253c260e60Schristos 8263c260e60Schristos pid = fork(); 8273c260e60Schristos if (pid < 0) { 8283c260e60Schristos perror("fork"); 8293c260e60Schristos return -1; 8303c260e60Schristos } 8313c260e60Schristos 8323c260e60Schristos if (pid == 0) { 8333c260e60Schristos /* run the external command in the child process */ 834fe1a092fSchristos #define MAX_ARG 30 8353c260e60Schristos char *_program, *_arg, *pos; 8363c260e60Schristos char *argv[MAX_ARG + 1]; 8373c260e60Schristos int i; 8383c260e60Schristos 8393c260e60Schristos _program = os_strdup(program); 8403c260e60Schristos _arg = os_strdup(arg); 8413c260e60Schristos 8423c260e60Schristos argv[0] = _program; 8433c260e60Schristos 8443c260e60Schristos i = 1; 8453c260e60Schristos pos = _arg; 8463c260e60Schristos while (i < MAX_ARG && pos && *pos) { 8473c260e60Schristos while (*pos == ' ') 8483c260e60Schristos pos++; 8493c260e60Schristos if (*pos == '\0') 8503c260e60Schristos break; 8513c260e60Schristos argv[i++] = pos; 8523c260e60Schristos pos = os_strchr(pos, ' '); 8533c260e60Schristos if (pos) 8543c260e60Schristos *pos++ = '\0'; 8553c260e60Schristos } 8563c260e60Schristos argv[i] = NULL; 8573c260e60Schristos 8583c260e60Schristos execv(program, argv); 8593c260e60Schristos perror("execv"); 8603c260e60Schristos os_free(_program); 8613c260e60Schristos os_free(_arg); 8623c260e60Schristos exit(0); 8633c260e60Schristos return -1; 8643c260e60Schristos } 8653c260e60Schristos 8663c260e60Schristos if (wait_completion) { 8673c260e60Schristos /* wait for the child process to complete in the parent */ 8683c260e60Schristos waitpid(pid, &pid_status, 0); 8693c260e60Schristos } 8703c260e60Schristos 8713c260e60Schristos return 0; 8723c260e60Schristos } 873