]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/wpa/src/utils/os_unix.c
Update hostapd/wpa_supplicant to 2.8 to fix multiple vulnerabilities.
[FreeBSD/FreeBSD.git] / contrib / wpa / src / utils / os_unix.c
1 /*
2  * OS specific functions for UNIX/POSIX systems
3  * Copyright (c) 2005-2019, 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 #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         if (TEST_FAIL())
84                 return -1;
85
86         while (1) {
87                 res = clock_gettime(clock_id, &ts);
88                 if (res == 0) {
89                         t->sec = ts.tv_sec;
90                         t->usec = ts.tv_nsec / 1000;
91                         return 0;
92                 }
93                 switch (clock_id) {
94 #ifdef CLOCK_BOOTTIME
95                 case CLOCK_BOOTTIME:
96                         clock_id = CLOCK_MONOTONIC;
97                         break;
98 #endif
99 #ifdef CLOCK_MONOTONIC
100                 case CLOCK_MONOTONIC:
101                         clock_id = CLOCK_REALTIME;
102                         break;
103 #endif
104                 case CLOCK_REALTIME:
105                         return -1;
106                 }
107         }
108 #else /* __MACH__ */
109         uint64_t abstime, nano;
110         static mach_timebase_info_data_t info = { 0, 0 };
111
112         if (!info.denom) {
113                 if (mach_timebase_info(&info) != KERN_SUCCESS)
114                         return -1;
115         }
116
117         abstime = mach_absolute_time();
118         nano = (abstime * info.numer) / info.denom;
119
120         t->sec = nano / NSEC_PER_SEC;
121         t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
122
123         return 0;
124 #endif /* __MACH__ */
125 }
126
127
128 int os_mktime(int year, int month, int day, int hour, int min, int sec,
129               os_time_t *t)
130 {
131         struct tm tm, *tm1;
132         time_t t_local, t1, t2;
133         os_time_t tz_offset;
134
135         if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
136             hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
137             sec > 60)
138                 return -1;
139
140         memset(&tm, 0, sizeof(tm));
141         tm.tm_year = year - 1900;
142         tm.tm_mon = month - 1;
143         tm.tm_mday = day;
144         tm.tm_hour = hour;
145         tm.tm_min = min;
146         tm.tm_sec = sec;
147
148         t_local = mktime(&tm);
149
150         /* figure out offset to UTC */
151         tm1 = localtime(&t_local);
152         if (tm1) {
153                 t1 = mktime(tm1);
154                 tm1 = gmtime(&t_local);
155                 if (tm1) {
156                         t2 = mktime(tm1);
157                         tz_offset = t2 - t1;
158                 } else
159                         tz_offset = 0;
160         } else
161                 tz_offset = 0;
162
163         *t = (os_time_t) t_local - tz_offset;
164         return 0;
165 }
166
167
168 int os_gmtime(os_time_t t, struct os_tm *tm)
169 {
170         struct tm *tm2;
171         time_t t2 = t;
172
173         tm2 = gmtime(&t2);
174         if (tm2 == NULL)
175                 return -1;
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;
182         return 0;
183 }
184
185
186 #ifdef __APPLE__
187 #include <fcntl.h>
188 static int os_daemon(int nochdir, int noclose)
189 {
190         int devnull;
191
192         if (chdir("/") < 0)
193                 return -1;
194
195         devnull = open("/dev/null", O_RDWR);
196         if (devnull < 0)
197                 return -1;
198
199         if (dup2(devnull, STDIN_FILENO) < 0) {
200                 close(devnull);
201                 return -1;
202         }
203
204         if (dup2(devnull, STDOUT_FILENO) < 0) {
205                 close(devnull);
206                 return -1;
207         }
208
209         if (dup2(devnull, STDERR_FILENO) < 0) {
210                 close(devnull);
211                 return -1;
212         }
213
214         return 0;
215 }
216 #else /* __APPLE__ */
217 #define os_daemon daemon
218 #endif /* __APPLE__ */
219
220
221 #ifdef __FreeBSD__
222 #include <err.h>
223 #include <libutil.h>
224 #include <stdint.h>
225 #endif /* __FreeBSD__ */
226
227 int os_daemonize(const char *pid_file)
228 {
229 #if defined(__uClinux__) || defined(__sun__)
230         return -1;
231 #else /* defined(__uClinux__) || defined(__sun__) */
232 #ifdef __FreeBSD__
233         pid_t otherpid;
234         struct pidfh *pfh;
235
236         pfh = pidfile_open(pid_file, 0600, &otherpid);
237         if (pfh == NULL) {
238                 if (errno == EEXIST) {
239                         errx(1, "Daemon already running, pid: %jd.",
240                             (intmax_t)otherpid);
241                 }
242                 warn("Cannot open or create pidfile.");
243         }
244 #endif /* __FreeBSD__ */
245
246         if (os_daemon(0, 0)) {
247                 perror("daemon");
248 #ifdef __FreeBSD__
249                 pidfile_remove(pfh);
250 #endif /* __FreeBSD__ */
251                 return -1;
252         }
253
254 #ifndef __FreeBSD__
255         if (pid_file) {
256                 FILE *f = fopen(pid_file, "w");
257                 if (f) {
258                         fprintf(f, "%u\n", getpid());
259                         fclose(f);
260                 }
261         }
262 #else /* __FreeBSD__ */
263         pidfile_write(pfh);
264 #endif /* __FreeBSD__ */
265
266         return -0;
267 #endif /* defined(__uClinux__) || defined(__sun__) */
268 }
269
270
271 void os_daemonize_terminate(const char *pid_file)
272 {
273         if (pid_file)
274                 unlink(pid_file);
275 }
276
277
278 int os_get_random(unsigned char *buf, size_t len)
279 {
280 #ifdef TEST_FUZZ
281         size_t i;
282
283         for (i = 0; i < len; i++)
284                 buf[i] = i & 0xff;
285         return 0;
286 #else /* TEST_FUZZ */
287         FILE *f;
288         size_t rc;
289
290         if (TEST_FAIL())
291                 return -1;
292
293         f = fopen("/dev/urandom", "rb");
294         if (f == NULL) {
295                 printf("Could not open /dev/urandom.\n");
296                 return -1;
297         }
298
299         rc = fread(buf, 1, len, f);
300         fclose(f);
301
302         return rc != len ? -1 : 0;
303 #endif /* TEST_FUZZ */
304 }
305
306
307 unsigned long os_random(void)
308 {
309         return random();
310 }
311
312
313 char * os_rel2abs_path(const char *rel_path)
314 {
315         char *buf = NULL, *cwd, *ret;
316         size_t len = 128, cwd_len, rel_len, ret_len;
317         int last_errno;
318
319         if (!rel_path)
320                 return NULL;
321
322         if (rel_path[0] == '/')
323                 return os_strdup(rel_path);
324
325         for (;;) {
326                 buf = os_malloc(len);
327                 if (buf == NULL)
328                         return NULL;
329                 cwd = getcwd(buf, len);
330                 if (cwd == NULL) {
331                         last_errno = errno;
332                         os_free(buf);
333                         if (last_errno != ERANGE)
334                                 return NULL;
335                         len *= 2;
336                         if (len > 2000)
337                                 return NULL;
338                 } else {
339                         buf[len - 1] = '\0';
340                         break;
341                 }
342         }
343
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);
348         if (ret) {
349                 os_memcpy(ret, cwd, cwd_len);
350                 ret[cwd_len] = '/';
351                 os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
352                 ret[ret_len - 1] = '\0';
353         }
354         os_free(buf);
355         return ret;
356 }
357
358
359 int os_program_init(void)
360 {
361 #ifdef ANDROID
362         /*
363          * We ignore errors here since errors are normal if we
364          * are already running as non-root.
365          */
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;
373
374         setgroups(ARRAY_SIZE(groups), groups);
375
376         prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
377
378         setgid(AID_WIFI);
379         setuid(AID_WIFI);
380
381         header.version = _LINUX_CAPABILITY_VERSION;
382         header.pid = 0;
383         cap.effective = cap.permitted =
384                 (1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
385         cap.inheritable = 0;
386         capset(&header, &cap);
387 #endif /* ANDROID */
388
389         return 0;
390 }
391
392
393 void os_program_deinit(void)
394 {
395 #ifdef WPA_TRACE
396         struct os_alloc_trace *a;
397         unsigned long total = 0;
398         dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
399                 total += a->len;
400                 if (a->magic != ALLOC_MAGIC) {
401                         wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
402                                    "len %lu",
403                                    a, a->magic, (unsigned long) a->len);
404                         continue;
405                 }
406                 wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
407                            a, (unsigned long) a->len);
408                 wpa_trace_dump("memleak", a);
409         }
410         if (total)
411                 wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
412                            (unsigned long) total);
413         wpa_trace_deinit();
414 #endif /* WPA_TRACE */
415 }
416
417
418 int os_setenv(const char *name, const char *value, int overwrite)
419 {
420         return setenv(name, value, overwrite);
421 }
422
423
424 int os_unsetenv(const char *name)
425 {
426 #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
427     defined(__OpenBSD__)
428         unsetenv(name);
429         return 0;
430 #else
431         return unsetenv(name);
432 #endif
433 }
434
435
436 char * os_readfile(const char *name, size_t *len)
437 {
438         FILE *f;
439         char *buf;
440         long pos;
441
442         f = fopen(name, "rb");
443         if (f == NULL)
444                 return NULL;
445
446         if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
447                 fclose(f);
448                 return NULL;
449         }
450         *len = pos;
451         if (fseek(f, 0, SEEK_SET) < 0) {
452                 fclose(f);
453                 return NULL;
454         }
455
456         buf = os_malloc(*len);
457         if (buf == NULL) {
458                 fclose(f);
459                 return NULL;
460         }
461
462         if (fread(buf, 1, *len, f) != *len) {
463                 fclose(f);
464                 os_free(buf);
465                 return NULL;
466         }
467
468         fclose(f);
469
470         return buf;
471 }
472
473
474 int os_file_exists(const char *fname)
475 {
476         return access(fname, F_OK) == 0;
477 }
478
479
480 int os_fdatasync(FILE *stream)
481 {
482         if (!fflush(stream)) {
483 #ifdef __linux__
484                 return fdatasync(fileno(stream));
485 #else /* !__linux__ */
486 #ifdef F_FULLFSYNC
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__ */
493         }
494
495         return -1;
496 }
497
498
499 #ifndef WPA_TRACE
500 void * os_zalloc(size_t size)
501 {
502         return calloc(1, size);
503 }
504 #endif /* WPA_TRACE */
505
506
507 size_t os_strlcpy(char *dest, const char *src, size_t siz)
508 {
509         const char *s = src;
510         size_t left = siz;
511
512         if (left) {
513                 /* Copy string up to the maximum size of the dest buffer */
514                 while (--left != 0) {
515                         if ((*dest++ = *s++) == '\0')
516                                 break;
517                 }
518         }
519
520         if (left == 0) {
521                 /* Not enough room for the string; force NUL-termination */
522                 if (siz != 0)
523                         *dest = '\0';
524                 while (*s++)
525                         ; /* determine total src string length */
526         }
527
528         return s - src - 1;
529 }
530
531
532 int os_memcmp_const(const void *a, const void *b, size_t len)
533 {
534         const u8 *aa = a;
535         const u8 *bb = b;
536         size_t i;
537         u8 res;
538
539         for (res = 0, i = 0; i < len; i++)
540                 res |= aa[i] ^ bb[i];
541
542         return res;
543 }
544
545
546 void * os_memdup(const void *src, size_t len)
547 {
548         void *r = os_malloc(len);
549
550         if (r && src)
551                 os_memcpy(r, src, len);
552         return r;
553 }
554
555
556 #ifdef WPA_TRACE
557
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;
561
562 static int testing_fail_alloc(void)
563 {
564         const char *func[WPA_TRACE_LEN];
565         size_t i, res, len;
566         char *pos, *next;
567         int match;
568
569         if (!wpa_trace_fail_after)
570                 return 0;
571
572         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
573         i = 0;
574         if (i < res && os_strcmp(func[i], __func__) == 0)
575                 i++;
576         if (i < res && os_strcmp(func[i], "os_malloc") == 0)
577                 i++;
578         if (i < res && os_strcmp(func[i], "os_zalloc") == 0)
579                 i++;
580         if (i < res && os_strcmp(func[i], "os_calloc") == 0)
581                 i++;
582         if (i < res && os_strcmp(func[i], "os_realloc") == 0)
583                 i++;
584         if (i < res && os_strcmp(func[i], "os_realloc_array") == 0)
585                 i++;
586         if (i < res && os_strcmp(func[i], "os_strdup") == 0)
587                 i++;
588         if (i < res && os_strcmp(func[i], "os_memdup") == 0)
589                 i++;
590
591         pos = wpa_trace_fail_func;
592
593         match = 0;
594         while (i < res) {
595                 int allow_skip = 1;
596                 int maybe = 0;
597
598                 if (*pos == '=') {
599                         allow_skip = 0;
600                         pos++;
601                 } else if (*pos == '?') {
602                         maybe = 1;
603                         pos++;
604                 }
605                 next = os_strchr(pos, ';');
606                 if (next)
607                         len = next - pos;
608                 else
609                         len = os_strlen(pos);
610                 if (os_memcmp(pos, func[i], len) != 0) {
611                         if (maybe && next) {
612                                 pos = next + 1;
613                                 continue;
614                         }
615                         if (allow_skip) {
616                                 i++;
617                                 continue;
618                         }
619                         return 0;
620                 }
621                 if (!next) {
622                         match = 1;
623                         break;
624                 }
625                 pos = next + 1;
626                 i++;
627         }
628         if (!match)
629                 return 0;
630
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",
637                                    (int) i, func[i]);
638                 return 1;
639         }
640
641         return 0;
642 }
643
644
645 char wpa_trace_test_fail_func[256] = { 0 };
646 unsigned int wpa_trace_test_fail_after;
647
648 int testing_test_fail(void)
649 {
650         const char *func[WPA_TRACE_LEN];
651         size_t i, res, len;
652         char *pos, *next;
653         int match;
654
655         if (!wpa_trace_test_fail_after)
656                 return 0;
657
658         res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
659         i = 0;
660         if (i < res && os_strcmp(func[i], __func__) == 0)
661                 i++;
662
663         pos = wpa_trace_test_fail_func;
664
665         match = 0;
666         while (i < res) {
667                 int allow_skip = 1;
668                 int maybe = 0;
669
670                 if (*pos == '=') {
671                         allow_skip = 0;
672                         pos++;
673                 } else if (*pos == '?') {
674                         maybe = 1;
675                         pos++;
676                 }
677                 next = os_strchr(pos, ';');
678                 if (next)
679                         len = next - pos;
680                 else
681                         len = os_strlen(pos);
682                 if (os_memcmp(pos, func[i], len) != 0) {
683                         if (maybe && next) {
684                                 pos = next + 1;
685                                 continue;
686                         }
687                         if (allow_skip) {
688                                 i++;
689                                 continue;
690                         }
691                         return 0;
692                 }
693                 if (!next) {
694                         match = 1;
695                         break;
696                 }
697                 pos = next + 1;
698                 i++;
699         }
700         if (!match)
701                 return 0;
702
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",
709                                    (int) i, func[i]);
710                 return 1;
711         }
712
713         return 0;
714 }
715
716 #else
717
718 static inline int testing_fail_alloc(void)
719 {
720         return 0;
721 }
722 #endif
723
724 void * os_malloc(size_t size)
725 {
726         struct os_alloc_trace *a;
727
728         if (testing_fail_alloc())
729                 return NULL;
730
731         a = malloc(sizeof(*a) + size);
732         if (a == NULL)
733                 return NULL;
734         a->magic = ALLOC_MAGIC;
735         dl_list_add(&alloc_list, &a->list);
736         a->len = size;
737         wpa_trace_record(a);
738         return a + 1;
739 }
740
741
742 void * os_realloc(void *ptr, size_t size)
743 {
744         struct os_alloc_trace *a;
745         size_t copy_len;
746         void *n;
747
748         if (ptr == NULL)
749                 return os_malloc(size);
750
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",
754                            a, a->magic,
755                            a->magic == FREED_MAGIC ? " (already freed)" : "");
756                 wpa_trace_show("Invalid os_realloc() call");
757                 abort();
758         }
759         n = os_malloc(size);
760         if (n == NULL)
761                 return NULL;
762         copy_len = a->len;
763         if (copy_len > size)
764                 copy_len = size;
765         os_memcpy(n, a + 1, copy_len);
766         os_free(ptr);
767         return n;
768 }
769
770
771 void os_free(void *ptr)
772 {
773         struct os_alloc_trace *a;
774
775         if (ptr == NULL)
776                 return;
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",
780                            a, a->magic,
781                            a->magic == FREED_MAGIC ? " (already freed)" : "");
782                 wpa_trace_show("Invalid os_free() call");
783                 abort();
784         }
785         dl_list_del(&a->list);
786         a->magic = FREED_MAGIC;
787
788         wpa_trace_check_ref(ptr);
789         free(a);
790 }
791
792
793 void * os_zalloc(size_t size)
794 {
795         void *ptr = os_malloc(size);
796         if (ptr)
797                 os_memset(ptr, 0, size);
798         return ptr;
799 }
800
801
802 char * os_strdup(const char *s)
803 {
804         size_t len;
805         char *d;
806         len = os_strlen(s);
807         d = os_malloc(len + 1);
808         if (d == NULL)
809                 return NULL;
810         os_memcpy(d, s, len);
811         d[len] = '\0';
812         return d;
813 }
814
815 #endif /* WPA_TRACE */
816
817
818 int os_exec(const char *program, const char *arg, int wait_completion)
819 {
820         pid_t pid;
821         int pid_status;
822
823         pid = fork();
824         if (pid < 0) {
825                 perror("fork");
826                 return -1;
827         }
828
829         if (pid == 0) {
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];
834                 int i;
835
836                 _program = os_strdup(program);
837                 _arg = os_strdup(arg);
838
839                 argv[0] = _program;
840
841                 i = 1;
842                 pos = _arg;
843                 while (i < MAX_ARG && pos && *pos) {
844                         while (*pos == ' ')
845                                 pos++;
846                         if (*pos == '\0')
847                                 break;
848                         argv[i++] = pos;
849                         pos = os_strchr(pos, ' ');
850                         if (pos)
851                                 *pos++ = '\0';
852                 }
853                 argv[i] = NULL;
854
855                 execv(program, argv);
856                 perror("execv");
857                 os_free(_program);
858                 os_free(_arg);
859                 exit(0);
860                 return -1;
861         }
862
863         if (wait_completion) {
864                 /* wait for the child process to complete in the parent */
865                 waitpid(pid, &pid_status, 0);
866         }
867
868         return 0;
869 }