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