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