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;
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 530 : void os_sleep(os_time_t sec, os_time_t usec)
45 : {
46 530 : if (sec)
47 0 : sleep(sec);
48 530 : if (usec)
49 530 : usleep(usec);
50 530 : }
51 :
52 :
53 3630934 : int os_get_time(struct os_time *t)
54 : {
55 : int res;
56 : struct timeval tv;
57 3630934 : res = gettimeofday(&tv, NULL);
58 3630934 : t->sec = tv.tv_sec;
59 3630934 : t->usec = tv.tv_usec;
60 3630934 : return res;
61 : }
62 :
63 :
64 949047 : 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 949047 : res = clock_gettime(clock_id, &ts);
78 949047 : if (res == 0) {
79 949047 : t->sec = ts.tv_sec;
80 949047 : t->usec = ts.tv_nsec / 1000;
81 949047 : 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 15312 : int os_get_random(unsigned char *buf, size_t len)
225 : {
226 : FILE *f;
227 : size_t rc;
228 :
229 15312 : f = fopen("/dev/urandom", "rb");
230 15312 : if (f == NULL) {
231 0 : printf("Could not open /dev/urandom.\n");
232 0 : return -1;
233 : }
234 :
235 15312 : rc = fread(buf, 1, len, f);
236 15312 : fclose(f);
237 :
238 15312 : return rc != len ? -1 : 0;
239 : }
240 :
241 :
242 4572 : unsigned long os_random(void)
243 : {
244 4572 : 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 : #ifdef WPA_TRACE
325 150 : dl_list_init(&alloc_list);
326 : #endif /* WPA_TRACE */
327 150 : return 0;
328 : }
329 :
330 :
331 85 : void os_program_deinit(void)
332 : {
333 : #ifdef WPA_TRACE
334 : struct os_alloc_trace *a;
335 85 : unsigned long total = 0;
336 85 : dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
337 0 : total += a->len;
338 0 : if (a->magic != ALLOC_MAGIC) {
339 0 : wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
340 : "len %lu",
341 : a, a->magic, (unsigned long) a->len);
342 0 : continue;
343 : }
344 0 : wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
345 : a, (unsigned long) a->len);
346 0 : wpa_trace_dump("memleak", a);
347 : }
348 85 : if (total)
349 0 : wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
350 : (unsigned long) total);
351 : #endif /* WPA_TRACE */
352 85 : }
353 :
354 :
355 0 : int os_setenv(const char *name, const char *value, int overwrite)
356 : {
357 0 : return setenv(name, value, overwrite);
358 : }
359 :
360 :
361 0 : int os_unsetenv(const char *name)
362 : {
363 : #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
364 : defined(__OpenBSD__)
365 : unsetenv(name);
366 : return 0;
367 : #else
368 0 : return unsetenv(name);
369 : #endif
370 : }
371 :
372 :
373 21 : char * os_readfile(const char *name, size_t *len)
374 : {
375 : FILE *f;
376 : char *buf;
377 : long pos;
378 :
379 21 : f = fopen(name, "rb");
380 21 : if (f == NULL)
381 2 : return NULL;
382 :
383 19 : if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
384 0 : fclose(f);
385 0 : return NULL;
386 : }
387 19 : *len = pos;
388 19 : if (fseek(f, 0, SEEK_SET) < 0) {
389 0 : fclose(f);
390 0 : return NULL;
391 : }
392 :
393 19 : buf = os_malloc(*len);
394 19 : if (buf == NULL) {
395 0 : fclose(f);
396 0 : return NULL;
397 : }
398 :
399 19 : if (fread(buf, 1, *len, f) != *len) {
400 0 : fclose(f);
401 0 : os_free(buf);
402 0 : return NULL;
403 : }
404 :
405 19 : fclose(f);
406 :
407 19 : return buf;
408 : }
409 :
410 :
411 0 : int os_file_exists(const char *fname)
412 : {
413 0 : FILE *f = fopen(fname, "rb");
414 0 : if (f == NULL)
415 0 : return 0;
416 0 : fclose(f);
417 0 : return 1;
418 : }
419 :
420 :
421 : #ifndef WPA_TRACE
422 : void * os_zalloc(size_t size)
423 : {
424 : return calloc(1, size);
425 : }
426 : #endif /* WPA_TRACE */
427 :
428 :
429 89957 : size_t os_strlcpy(char *dest, const char *src, size_t siz)
430 : {
431 89957 : const char *s = src;
432 89957 : size_t left = siz;
433 :
434 89957 : if (left) {
435 : /* Copy string up to the maximum size of the dest buffer */
436 640503 : while (--left != 0) {
437 550171 : if ((*dest++ = *s++) == '\0')
438 89582 : break;
439 : }
440 : }
441 :
442 89957 : if (left == 0) {
443 : /* Not enough room for the string; force NUL-termination */
444 375 : if (siz != 0)
445 375 : *dest = '\0';
446 375 : while (*s++)
447 : ; /* determine total src string length */
448 : }
449 :
450 89957 : return s - src - 1;
451 : }
452 :
453 :
454 23033 : int os_memcmp_const(const void *a, const void *b, size_t len)
455 : {
456 23033 : const u8 *aa = a;
457 23033 : const u8 *bb = b;
458 : size_t i;
459 : u8 res;
460 :
461 382891 : for (res = 0, i = 0; i < len; i++)
462 359858 : res |= aa[i] ^ bb[i];
463 :
464 23033 : return res;
465 : }
466 :
467 :
468 : #ifdef WPA_TRACE
469 :
470 : #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
471 : char wpa_trace_fail_func[256] = { 0 };
472 : unsigned int wpa_trace_fail_after;
473 :
474 2160230 : static int testing_fail_alloc(void)
475 : {
476 : const char *func[WPA_TRACE_LEN];
477 : size_t i, res, len;
478 : char *pos, *next;
479 : int match;
480 :
481 2160230 : if (!wpa_trace_fail_after)
482 2110968 : return 0;
483 :
484 49262 : res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
485 49262 : i = 0;
486 49262 : if (i < res && os_strcmp(func[i], __func__) == 0)
487 49262 : i++;
488 49262 : if (i < res && os_strcmp(func[i], "os_malloc") == 0)
489 49262 : i++;
490 49262 : if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
491 15830 : i++;
492 49262 : if (i < res && os_strcmp(func[i], "os_calloc") == 0)
493 1643 : i++;
494 49262 : if (i < res && os_strcmp(func[i], "os_realloc") == 0)
495 4759 : i++;
496 49262 : if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
497 4751 : i++;
498 49262 : if (i < res && os_strcmp(func[i], "os_strdup") == 0)
499 3900 : i++;
500 :
501 49262 : pos = wpa_trace_fail_func;
502 :
503 49262 : match = 0;
504 545692 : while (i < res) {
505 472152 : int allow_skip = 1;
506 472152 : int maybe = 0;
507 :
508 472152 : if (*pos == '=') {
509 866 : allow_skip = 0;
510 866 : pos++;
511 471286 : } else if (*pos == '?') {
512 6 : maybe = 1;
513 6 : pos++;
514 : }
515 472152 : next = os_strchr(pos, ';');
516 472152 : if (next)
517 7567 : len = next - pos;
518 : else
519 464585 : len = os_strlen(pos);
520 472152 : if (os_memcmp(pos, func[i], len) != 0) {
521 447140 : if (maybe && next) {
522 0 : pos = next + 1;
523 0 : continue;
524 : }
525 447140 : if (allow_skip) {
526 446351 : i++;
527 446351 : continue;
528 : }
529 789 : return 0;
530 : }
531 25012 : if (!next) {
532 24195 : match = 1;
533 24195 : break;
534 : }
535 817 : pos = next + 1;
536 817 : i++;
537 : }
538 48473 : if (!match)
539 24278 : return 0;
540 :
541 24195 : wpa_trace_fail_after--;
542 24195 : if (wpa_trace_fail_after == 0) {
543 546 : wpa_printf(MSG_INFO, "TESTING: fail allocation at %s",
544 : wpa_trace_fail_func);
545 7218 : for (i = 0; i < res; i++)
546 6672 : wpa_printf(MSG_INFO, "backtrace[%d] = %s",
547 : (int) i, func[i]);
548 546 : return 1;
549 : }
550 :
551 23649 : return 0;
552 : }
553 :
554 : #else
555 :
556 : static inline int testing_fail_alloc(void)
557 : {
558 : return 0;
559 : }
560 : #endif
561 :
562 2160230 : void * os_malloc(size_t size)
563 : {
564 : struct os_alloc_trace *a;
565 :
566 2160230 : if (testing_fail_alloc())
567 546 : return NULL;
568 :
569 2159684 : a = malloc(sizeof(*a) + size);
570 2159684 : if (a == NULL)
571 0 : return NULL;
572 2159684 : a->magic = ALLOC_MAGIC;
573 2159684 : dl_list_add(&alloc_list, &a->list);
574 2159684 : a->len = size;
575 2159684 : wpa_trace_record(a);
576 2159684 : return a + 1;
577 : }
578 :
579 :
580 411702 : void * os_realloc(void *ptr, size_t size)
581 : {
582 : struct os_alloc_trace *a;
583 : size_t copy_len;
584 : void *n;
585 :
586 411702 : if (ptr == NULL)
587 39914 : return os_malloc(size);
588 :
589 371788 : a = (struct os_alloc_trace *) ptr - 1;
590 371788 : if (a->magic != ALLOC_MAGIC) {
591 0 : wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
592 : a, a->magic,
593 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
594 0 : wpa_trace_show("Invalid os_realloc() call");
595 0 : abort();
596 : }
597 371788 : n = os_malloc(size);
598 371788 : if (n == NULL)
599 12 : return NULL;
600 371776 : copy_len = a->len;
601 371776 : if (copy_len > size)
602 2691 : copy_len = size;
603 371776 : os_memcpy(n, a + 1, copy_len);
604 371776 : os_free(ptr);
605 371776 : return n;
606 : }
607 :
608 :
609 2640922 : void os_free(void *ptr)
610 : {
611 : struct os_alloc_trace *a;
612 :
613 2640922 : if (ptr == NULL)
614 3122170 : return;
615 2159674 : a = (struct os_alloc_trace *) ptr - 1;
616 2159674 : if (a->magic != ALLOC_MAGIC) {
617 0 : wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
618 : a, a->magic,
619 0 : a->magic == FREED_MAGIC ? " (already freed)" : "");
620 0 : wpa_trace_show("Invalid os_free() call");
621 0 : abort();
622 : }
623 2159674 : dl_list_del(&a->list);
624 2159674 : a->magic = FREED_MAGIC;
625 :
626 2159674 : wpa_trace_check_ref(ptr);
627 2159674 : free(a);
628 : }
629 :
630 :
631 467676 : void * os_zalloc(size_t size)
632 : {
633 467676 : void *ptr = os_malloc(size);
634 467676 : if (ptr)
635 467452 : os_memset(ptr, 0, size);
636 467676 : return ptr;
637 : }
638 :
639 :
640 188666 : char * os_strdup(const char *s)
641 : {
642 : size_t len;
643 : char *d;
644 188666 : len = os_strlen(s);
645 188666 : d = os_malloc(len + 1);
646 188666 : if (d == NULL)
647 54 : return NULL;
648 188612 : os_memcpy(d, s, len);
649 188612 : d[len] = '\0';
650 188612 : return d;
651 : }
652 :
653 : #endif /* WPA_TRACE */
654 :
655 :
656 0 : int os_exec(const char *program, const char *arg, int wait_completion)
657 : {
658 : pid_t pid;
659 : int pid_status;
660 :
661 0 : pid = fork();
662 0 : if (pid < 0) {
663 0 : perror("fork");
664 0 : return -1;
665 : }
666 :
667 0 : if (pid == 0) {
668 : /* run the external command in the child process */
669 0 : const int MAX_ARG = 30;
670 : char *_program, *_arg, *pos;
671 0 : char *argv[MAX_ARG + 1];
672 : int i;
673 :
674 0 : _program = os_strdup(program);
675 0 : _arg = os_strdup(arg);
676 :
677 0 : argv[0] = _program;
678 :
679 0 : i = 1;
680 0 : pos = _arg;
681 0 : while (i < MAX_ARG && pos && *pos) {
682 0 : while (*pos == ' ')
683 0 : pos++;
684 0 : if (*pos == '\0')
685 0 : break;
686 0 : argv[i++] = pos;
687 0 : pos = os_strchr(pos, ' ');
688 0 : if (pos)
689 0 : *pos++ = '\0';
690 : }
691 0 : argv[i] = NULL;
692 :
693 0 : execv(program, argv);
694 0 : perror("execv");
695 0 : os_free(_program);
696 0 : os_free(_arg);
697 0 : exit(0);
698 : return -1;
699 : }
700 :
701 0 : if (wait_completion) {
702 : /* wait for the child process to complete in the parent */
703 0 : waitpid(pid, &pid_status, 0);
704 : }
705 :
706 0 : return 0;
707 : }
|