2 * OS specific functions for UNIX/POSIX systems
3 * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
15 #include <sys/capability.h>
16 #include <sys/prctl.h>
17 #include <private/android_filesystem_config.h>
21 #include <CoreServices/CoreServices.h>
22 #include <mach/mach.h>
23 #include <mach/mach_time.h>
31 #include "wpa_debug.h"
35 static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
37 #define ALLOC_MAGIC 0xa84ef1b2
38 #define FREED_MAGIC 0x67fd487a
40 struct os_alloc_trace {
45 } __attribute__((aligned(16)));
47 #endif /* WPA_TRACE */
50 void os_sleep(os_time_t sec, os_time_t usec)
59 int os_get_time(struct os_time *t)
63 res = gettimeofday(&tv, NULL);
70 int os_get_reltime(struct os_reltime *t)
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;
78 static clockid_t clock_id = CLOCK_REALTIME;
87 res = clock_gettime(clock_id, &ts);
90 t->usec = ts.tv_nsec / 1000;
96 clock_id = CLOCK_MONOTONIC;
99 #ifdef CLOCK_MONOTONIC
100 case CLOCK_MONOTONIC:
101 clock_id = CLOCK_REALTIME;
109 uint64_t abstime, nano;
110 static mach_timebase_info_data_t info = { 0, 0 };
113 if (mach_timebase_info(&info) != KERN_SUCCESS)
117 abstime = mach_absolute_time();
118 nano = (abstime * info.numer) / info.denom;
120 t->sec = nano / NSEC_PER_SEC;
121 t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
124 #endif /* __MACH__ */
128 int os_mktime(int year, int month, int day, int hour, int min, int sec,
132 time_t t_local, t1, t2;
135 if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
136 hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
140 memset(&tm, 0, sizeof(tm));
141 tm.tm_year = year - 1900;
142 tm.tm_mon = month - 1;
148 t_local = mktime(&tm);
150 /* figure out offset to UTC */
151 tm1 = localtime(&t_local);
154 tm1 = gmtime(&t_local);
163 *t = (os_time_t) t_local - tz_offset;
168 int os_gmtime(os_time_t t, struct os_tm *tm)
176 tm->sec = tm2->tm_sec;
177 tm->min = tm2->tm_min;
178 tm->hour = tm2->tm_hour;
179 tm->day = tm2->tm_mday;
180 tm->month = tm2->tm_mon + 1;
181 tm->year = tm2->tm_year + 1900;
188 static int os_daemon(int nochdir, int noclose)
195 devnull = open("/dev/null", O_RDWR);
199 if (dup2(devnull, STDIN_FILENO) < 0) {
204 if (dup2(devnull, STDOUT_FILENO) < 0) {
209 if (dup2(devnull, STDERR_FILENO) < 0) {
216 #else /* __APPLE__ */
217 #define os_daemon daemon
218 #endif /* __APPLE__ */
225 #endif /* __FreeBSD__ */
227 int os_daemonize(const char *pid_file)
229 #if defined(__uClinux__) || defined(__sun__)
231 #else /* defined(__uClinux__) || defined(__sun__) */
236 pfh = pidfile_open(pid_file, 0600, &otherpid);
238 if (errno == EEXIST) {
239 errx(1, "Daemon already running, pid: %jd.",
242 warn("Cannot open or create pidfile.");
244 #endif /* __FreeBSD__ */
246 if (os_daemon(0, 0)) {
250 #endif /* __FreeBSD__ */
256 FILE *f = fopen(pid_file, "w");
258 fprintf(f, "%u\n", getpid());
262 #else /* __FreeBSD__ */
264 #endif /* __FreeBSD__ */
267 #endif /* defined(__uClinux__) || defined(__sun__) */
271 void os_daemonize_terminate(const char *pid_file)
278 int os_get_random(unsigned char *buf, size_t len)
283 for (i = 0; i < len; i++)
286 #else /* TEST_FUZZ */
293 f = fopen("/dev/urandom", "rb");
295 printf("Could not open /dev/urandom.\n");
299 rc = fread(buf, 1, len, f);
302 return rc != len ? -1 : 0;
303 #endif /* TEST_FUZZ */
307 unsigned long os_random(void)
313 char * os_rel2abs_path(const char *rel_path)
315 char *buf = NULL, *cwd, *ret;
316 size_t len = 128, cwd_len, rel_len, ret_len;
322 if (rel_path[0] == '/')
323 return os_strdup(rel_path);
326 buf = os_malloc(len);
329 cwd = getcwd(buf, len);
333 if (last_errno != ERANGE)
344 cwd_len = os_strlen(cwd);
345 rel_len = os_strlen(rel_path);
346 ret_len = cwd_len + 1 + rel_len + 1;
347 ret = os_malloc(ret_len);
349 os_memcpy(ret, cwd, cwd_len);
351 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
352 ret[ret_len - 1] = '\0';
359 int os_program_init(void)
363 * We ignore errors here since errors are normal if we
364 * are already running as non-root.
366 #ifdef ANDROID_SETGROUPS_OVERRIDE
367 gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
368 #else /* ANDROID_SETGROUPS_OVERRIDE */
369 gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
370 #endif /* ANDROID_SETGROUPS_OVERRIDE */
371 struct __user_cap_header_struct header;
372 struct __user_cap_data_struct cap;
374 setgroups(ARRAY_SIZE(groups), groups);
376 prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
381 header.version = _LINUX_CAPABILITY_VERSION;
383 cap.effective = cap.permitted =
384 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
386 capset(&header, &cap);
393 void os_program_deinit(void)
396 struct os_alloc_trace *a;
397 unsigned long total = 0;
398 dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
400 if (a->magic != ALLOC_MAGIC) {
401 wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
403 a, a->magic, (unsigned long) a->len);
406 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
407 a, (unsigned long) a->len);
408 wpa_trace_dump("memleak", a);
411 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
412 (unsigned long) total);
414 #endif /* WPA_TRACE */
418 int os_setenv(const char *name, const char *value, int overwrite)
420 return setenv(name, value, overwrite);
424 int os_unsetenv(const char *name)
426 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
431 return unsetenv(name);
436 char * os_readfile(const char *name, size_t *len)
442 f = fopen(name, "rb");
446 if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
451 if (fseek(f, 0, SEEK_SET) < 0) {
456 buf = os_malloc(*len);
462 if (fread(buf, 1, *len, f) != *len) {
474 int os_file_exists(const char *fname)
476 return access(fname, F_OK) == 0;
480 int os_fdatasync(FILE *stream)
482 if (!fflush(stream)) {
484 return fdatasync(fileno(stream));
485 #else /* !__linux__ */
487 /* OS X does not implement fdatasync(). */
488 return fcntl(fileno(stream), F_FULLFSYNC);
489 #else /* F_FULLFSYNC */
490 return fsync(fileno(stream));
491 #endif /* F_FULLFSYNC */
492 #endif /* __linux__ */
500 void * os_zalloc(size_t size)
502 return calloc(1, size);
504 #endif /* WPA_TRACE */
507 size_t os_strlcpy(char *dest, const char *src, size_t siz)
513 /* Copy string up to the maximum size of the dest buffer */
514 while (--left != 0) {
515 if ((*dest++ = *s++) == '\0')
521 /* Not enough room for the string; force NUL-termination */
525 ; /* determine total src string length */
532 int os_memcmp_const(const void *a, const void *b, size_t len)
539 for (res = 0, i = 0; i < len; i++)
540 res |= aa[i] ^ bb[i];
546 void * os_memdup(const void *src, size_t len)
548 void *r = os_malloc(len);
551 os_memcpy(r, src, len);
558 #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
559 char wpa_trace_fail_func[256] = { 0 };
560 unsigned int wpa_trace_fail_after;
562 static int testing_fail_alloc(void)
564 const char *func[WPA_TRACE_LEN];
569 if (!wpa_trace_fail_after)
572 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
574 if (i < res && os_strcmp(func[i], __func__) == 0)
576 if (i < res && os_strcmp(func[i], "os_malloc") == 0)
578 if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
580 if (i < res && os_strcmp(func[i], "os_calloc") == 0)
582 if (i < res && os_strcmp(func[i], "os_realloc") == 0)
584 if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
586 if (i < res && os_strcmp(func[i], "os_strdup") == 0)
588 if (i < res && os_strcmp(func[i], "os_memdup") == 0)
591 pos = wpa_trace_fail_func;
601 } else if (*pos == '?') {
605 next = os_strchr(pos, ';');
609 len = os_strlen(pos);
610 if (os_memcmp(pos, func[i], len) != 0) {
631 wpa_trace_fail_after--;
632 if (wpa_trace_fail_after == 0) {
633 wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
634 wpa_trace_fail_func);
635 for (i = 0; i < res; i++)
636 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
645 char wpa_trace_test_fail_func[256] = { 0 };
646 unsigned int wpa_trace_test_fail_after;
648 int testing_test_fail(void)
650 const char *func[WPA_TRACE_LEN];
655 if (!wpa_trace_test_fail_after)
658 res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
660 if (i < res && os_strcmp(func[i], __func__) == 0)
663 pos = wpa_trace_test_fail_func;
673 } else if (*pos == '?') {
677 next = os_strchr(pos, ';');
681 len = os_strlen(pos);
682 if (os_memcmp(pos, func[i], len) != 0) {
703 wpa_trace_test_fail_after--;
704 if (wpa_trace_test_fail_after == 0) {
705 wpa_printf(MSG_INFO, "TESTING: fail at %s",
706 wpa_trace_test_fail_func);
707 for (i = 0; i < res; i++)
708 wpa_printf(MSG_INFO, "backtrace[%d] = %s",
718 static inline int testing_fail_alloc(void)
724 void * os_malloc(size_t size)
726 struct os_alloc_trace *a;
728 if (testing_fail_alloc())
731 a = malloc(sizeof(*a) + size);
734 a->magic = ALLOC_MAGIC;
735 dl_list_add(&alloc_list, &a->list);
742 void * os_realloc(void *ptr, size_t size)
744 struct os_alloc_trace *a;
749 return os_malloc(size);
751 a = (struct os_alloc_trace *) ptr - 1;
752 if (a->magic != ALLOC_MAGIC) {
753 wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
755 a->magic == FREED_MAGIC ? " (already freed)" : "");
756 wpa_trace_show("Invalid os_realloc() call");
765 os_memcpy(n, a + 1, copy_len);
771 void os_free(void *ptr)
773 struct os_alloc_trace *a;
777 a = (struct os_alloc_trace *) ptr - 1;
778 if (a->magic != ALLOC_MAGIC) {
779 wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
781 a->magic == FREED_MAGIC ? " (already freed)" : "");
782 wpa_trace_show("Invalid os_free() call");
785 dl_list_del(&a->list);
786 a->magic = FREED_MAGIC;
788 wpa_trace_check_ref(ptr);
793 void * os_zalloc(size_t size)
795 void *ptr = os_malloc(size);
797 os_memset(ptr, 0, size);
802 char * os_strdup(const char *s)
807 d = os_malloc(len + 1);
810 os_memcpy(d, s, len);
815 #endif /* WPA_TRACE */
818 int os_exec(const char *program, const char *arg, int wait_completion)
830 /* run the external command in the child process */
831 const int MAX_ARG = 30;
832 char *_program, *_arg, *pos;
833 char *argv[MAX_ARG + 1];
836 _program = os_strdup(program);
837 _arg = os_strdup(arg);
843 while (i < MAX_ARG && pos && *pos) {
849 pos = os_strchr(pos, ' ');
855 execv(program, argv);
863 if (wait_completion) {
864 /* wait for the child process to complete in the parent */
865 waitpid(pid, &pid_status, 0);