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