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

55-freebsd-126-freebsd-12
Last change on this file since 9521c08 was 9521c08, checked in by Christian Mauderer <Christian.Mauderer@…>, on 11/09/17 at 13:35:13

wpa_supplicant: Use arc4random instead of getentropy.

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