source: rtems-libbsd/freebsd/contrib/wpa/src/utils/os_unix.c

6-freebsd-12
Last change on this file was 705e362, checked in by Sebastian Huber <sebastian.huber@…>, on 06/05/19 at 09:35:39

Update to FreeBSD stable/12 2019-06-05

Git mirror commit 78576620f2689e23144a1cf1bf55106cc6abe2b7.

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