xref: /netbsd-src/external/bsd/wpa/dist/src/utils/os_unix.c (revision 45d3cc13f775755ee348416d64536fb30df46e06)
18dbcf02cSchristos /*
28dbcf02cSchristos  * OS specific functions for UNIX/POSIX systems
3460bb4fcSchristos  * Copyright (c) 2005-2019, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos  *
5e604d861Schristos  * This software may be distributed under the terms of the BSD license.
6e604d861Schristos  * See README for more details.
78dbcf02cSchristos  */
88dbcf02cSchristos 
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos 
11111b9fd8Schristos #include <time.h>
123c260e60Schristos #include <sys/wait.h>
13111b9fd8Schristos 
14111b9fd8Schristos #ifdef ANDROID
153c260e60Schristos #include <sys/capability.h>
163c260e60Schristos #include <sys/prctl.h>
17111b9fd8Schristos #include <private/android_filesystem_config.h>
18111b9fd8Schristos #endif /* ANDROID */
19111b9fd8Schristos 
20ecc36642Schristos #ifdef __MACH__
21ecc36642Schristos #include <CoreServices/CoreServices.h>
22ecc36642Schristos #include <mach/mach.h>
23ecc36642Schristos #include <mach/mach_time.h>
24ecc36642Schristos #endif /* __MACH__ */
25ecc36642Schristos 
268dbcf02cSchristos #include "os.h"
273c260e60Schristos #include "common.h"
288dbcf02cSchristos 
298dbcf02cSchristos #ifdef WPA_TRACE
308dbcf02cSchristos 
318dbcf02cSchristos #include "wpa_debug.h"
328dbcf02cSchristos #include "trace.h"
33e604d861Schristos #include "list.h"
348dbcf02cSchristos 
35299bbf24Schristos static struct dl_list alloc_list = DL_LIST_HEAD_INIT(alloc_list);
368dbcf02cSchristos 
378dbcf02cSchristos #define ALLOC_MAGIC 0xa84ef1b2
388dbcf02cSchristos #define FREED_MAGIC 0x67fd487a
398dbcf02cSchristos 
408dbcf02cSchristos struct os_alloc_trace {
418dbcf02cSchristos 	unsigned int magic;
42*45d3cc13Schristos 	struct dl_list list __attribute__((aligned(16)));
438dbcf02cSchristos 	size_t len;
448dbcf02cSchristos 	WPA_TRACE_INFO
45ecc36642Schristos } __attribute__((aligned(16)));
468dbcf02cSchristos 
478dbcf02cSchristos #endif /* WPA_TRACE */
488dbcf02cSchristos 
498dbcf02cSchristos 
508dbcf02cSchristos void os_sleep(os_time_t sec, os_time_t usec)
518dbcf02cSchristos {
52*45d3cc13Schristos #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
53*45d3cc13Schristos 	const struct timespec req = { sec, usec * 1000 };
54*45d3cc13Schristos 
55*45d3cc13Schristos 	nanosleep(&req, NULL);
56*45d3cc13Schristos #else
578dbcf02cSchristos 	if (sec)
588dbcf02cSchristos 		sleep(sec);
598dbcf02cSchristos 	if (usec)
608dbcf02cSchristos 		usleep(usec);
61*45d3cc13Schristos #endif
628dbcf02cSchristos }
638dbcf02cSchristos 
648dbcf02cSchristos 
658dbcf02cSchristos int os_get_time(struct os_time *t)
668dbcf02cSchristos {
678dbcf02cSchristos 	int res;
688dbcf02cSchristos 	struct timeval tv;
698dbcf02cSchristos 	res = gettimeofday(&tv, NULL);
708dbcf02cSchristos 	t->sec = tv.tv_sec;
718dbcf02cSchristos 	t->usec = tv.tv_usec;
728dbcf02cSchristos 	return res;
738dbcf02cSchristos }
748dbcf02cSchristos 
758dbcf02cSchristos 
763c260e60Schristos int os_get_reltime(struct os_reltime *t)
773c260e60Schristos {
78ecc36642Schristos #ifndef __MACH__
793c260e60Schristos #if defined(CLOCK_BOOTTIME)
803c260e60Schristos 	static clockid_t clock_id = CLOCK_BOOTTIME;
813c260e60Schristos #elif defined(CLOCK_MONOTONIC)
823c260e60Schristos 	static clockid_t clock_id = CLOCK_MONOTONIC;
833c260e60Schristos #else
843c260e60Schristos 	static clockid_t clock_id = CLOCK_REALTIME;
853c260e60Schristos #endif
863c260e60Schristos 	struct timespec ts;
873c260e60Schristos 	int res;
883c260e60Schristos 
89be6b3c4dSchristos 	if (TEST_FAIL())
90be6b3c4dSchristos 		return -1;
91be6b3c4dSchristos 
923c260e60Schristos 	while (1) {
933c260e60Schristos 		res = clock_gettime(clock_id, &ts);
943c260e60Schristos 		if (res == 0) {
953c260e60Schristos 			t->sec = ts.tv_sec;
963c260e60Schristos 			t->usec = ts.tv_nsec / 1000;
973c260e60Schristos 			return 0;
983c260e60Schristos 		}
993c260e60Schristos 		switch (clock_id) {
1003c260e60Schristos #ifdef CLOCK_BOOTTIME
1013c260e60Schristos 		case CLOCK_BOOTTIME:
1023c260e60Schristos 			clock_id = CLOCK_MONOTONIC;
1033c260e60Schristos 			break;
1043c260e60Schristos #endif
1053c260e60Schristos #ifdef CLOCK_MONOTONIC
1063c260e60Schristos 		case CLOCK_MONOTONIC:
1073c260e60Schristos 			clock_id = CLOCK_REALTIME;
1083c260e60Schristos 			break;
1093c260e60Schristos #endif
1103c260e60Schristos 		case CLOCK_REALTIME:
1113c260e60Schristos 			return -1;
1123c260e60Schristos 		}
1133c260e60Schristos 	}
114ecc36642Schristos #else /* __MACH__ */
115ecc36642Schristos 	uint64_t abstime, nano;
116ecc36642Schristos 	static mach_timebase_info_data_t info = { 0, 0 };
117ecc36642Schristos 
118ecc36642Schristos 	if (!info.denom) {
119ecc36642Schristos 		if (mach_timebase_info(&info) != KERN_SUCCESS)
120ecc36642Schristos 			return -1;
121ecc36642Schristos 	}
122ecc36642Schristos 
123ecc36642Schristos 	abstime = mach_absolute_time();
124ecc36642Schristos 	nano = (abstime * info.numer) / info.denom;
125ecc36642Schristos 
126ecc36642Schristos 	t->sec = nano / NSEC_PER_SEC;
127ecc36642Schristos 	t->usec = (nano - (((uint64_t) t->sec) * NSEC_PER_SEC)) / NSEC_PER_USEC;
128ecc36642Schristos 
129ecc36642Schristos 	return 0;
130ecc36642Schristos #endif /* __MACH__ */
1313c260e60Schristos }
1323c260e60Schristos 
1333c260e60Schristos 
1348dbcf02cSchristos int os_mktime(int year, int month, int day, int hour, int min, int sec,
1358dbcf02cSchristos 	      os_time_t *t)
1368dbcf02cSchristos {
1378dbcf02cSchristos 	struct tm tm, *tm1;
1388dbcf02cSchristos 	time_t t_local, t1, t2;
1398dbcf02cSchristos 	os_time_t tz_offset;
1408dbcf02cSchristos 
1418dbcf02cSchristos 	if (year < 1970 || month < 1 || month > 12 || day < 1 || day > 31 ||
1428dbcf02cSchristos 	    hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 ||
1438dbcf02cSchristos 	    sec > 60)
1448dbcf02cSchristos 		return -1;
1458dbcf02cSchristos 
1468dbcf02cSchristos 	memset(&tm, 0, sizeof(tm));
1478dbcf02cSchristos 	tm.tm_year = year - 1900;
1488dbcf02cSchristos 	tm.tm_mon = month - 1;
1498dbcf02cSchristos 	tm.tm_mday = day;
1508dbcf02cSchristos 	tm.tm_hour = hour;
1518dbcf02cSchristos 	tm.tm_min = min;
1528dbcf02cSchristos 	tm.tm_sec = sec;
1538dbcf02cSchristos 
1548dbcf02cSchristos 	t_local = mktime(&tm);
1558dbcf02cSchristos 
1568dbcf02cSchristos 	/* figure out offset to UTC */
1578dbcf02cSchristos 	tm1 = localtime(&t_local);
1588dbcf02cSchristos 	if (tm1) {
1598dbcf02cSchristos 		t1 = mktime(tm1);
1608dbcf02cSchristos 		tm1 = gmtime(&t_local);
1618dbcf02cSchristos 		if (tm1) {
1628dbcf02cSchristos 			t2 = mktime(tm1);
1638dbcf02cSchristos 			tz_offset = t2 - t1;
1648dbcf02cSchristos 		} else
1658dbcf02cSchristos 			tz_offset = 0;
1668dbcf02cSchristos 	} else
1678dbcf02cSchristos 		tz_offset = 0;
1688dbcf02cSchristos 
1698dbcf02cSchristos 	*t = (os_time_t) t_local - tz_offset;
1708dbcf02cSchristos 	return 0;
1718dbcf02cSchristos }
1728dbcf02cSchristos 
1738dbcf02cSchristos 
174111b9fd8Schristos int os_gmtime(os_time_t t, struct os_tm *tm)
175111b9fd8Schristos {
176111b9fd8Schristos 	struct tm *tm2;
177111b9fd8Schristos 	time_t t2 = t;
178111b9fd8Schristos 
179111b9fd8Schristos 	tm2 = gmtime(&t2);
180111b9fd8Schristos 	if (tm2 == NULL)
181111b9fd8Schristos 		return -1;
182111b9fd8Schristos 	tm->sec = tm2->tm_sec;
183111b9fd8Schristos 	tm->min = tm2->tm_min;
184111b9fd8Schristos 	tm->hour = tm2->tm_hour;
185111b9fd8Schristos 	tm->day = tm2->tm_mday;
186111b9fd8Schristos 	tm->month = tm2->tm_mon + 1;
187111b9fd8Schristos 	tm->year = tm2->tm_year + 1900;
188111b9fd8Schristos 	return 0;
189111b9fd8Schristos }
190111b9fd8Schristos 
191111b9fd8Schristos 
1928dbcf02cSchristos #ifdef __APPLE__
1938dbcf02cSchristos #include <fcntl.h>
1948dbcf02cSchristos static int os_daemon(int nochdir, int noclose)
1958dbcf02cSchristos {
1968dbcf02cSchristos 	int devnull;
1978dbcf02cSchristos 
1988dbcf02cSchristos 	if (chdir("/") < 0)
1998dbcf02cSchristos 		return -1;
2008dbcf02cSchristos 
2018dbcf02cSchristos 	devnull = open("/dev/null", O_RDWR);
2028dbcf02cSchristos 	if (devnull < 0)
2038dbcf02cSchristos 		return -1;
2048dbcf02cSchristos 
2058dbcf02cSchristos 	if (dup2(devnull, STDIN_FILENO) < 0) {
2068dbcf02cSchristos 		close(devnull);
2078dbcf02cSchristos 		return -1;
2088dbcf02cSchristos 	}
2098dbcf02cSchristos 
2108dbcf02cSchristos 	if (dup2(devnull, STDOUT_FILENO) < 0) {
2118dbcf02cSchristos 		close(devnull);
2128dbcf02cSchristos 		return -1;
2138dbcf02cSchristos 	}
2148dbcf02cSchristos 
2158dbcf02cSchristos 	if (dup2(devnull, STDERR_FILENO) < 0) {
2168dbcf02cSchristos 		close(devnull);
2178dbcf02cSchristos 		return -1;
2188dbcf02cSchristos 	}
2198dbcf02cSchristos 
2208dbcf02cSchristos 	return 0;
2218dbcf02cSchristos }
2228dbcf02cSchristos #else /* __APPLE__ */
2238dbcf02cSchristos #define os_daemon daemon
2248dbcf02cSchristos #endif /* __APPLE__ */
2258dbcf02cSchristos 
2268dbcf02cSchristos 
2278dbcf02cSchristos int os_daemonize(const char *pid_file)
2288dbcf02cSchristos {
229111b9fd8Schristos #if defined(__uClinux__) || defined(__sun__)
2308dbcf02cSchristos 	return -1;
231111b9fd8Schristos #else /* defined(__uClinux__) || defined(__sun__) */
2328dbcf02cSchristos 	if (os_daemon(0, 0)) {
2338dbcf02cSchristos 		perror("daemon");
2348dbcf02cSchristos 		return -1;
2358dbcf02cSchristos 	}
2368dbcf02cSchristos 
2378dbcf02cSchristos 	if (pid_file) {
2388dbcf02cSchristos 		FILE *f = fopen(pid_file, "w");
2398dbcf02cSchristos 		if (f) {
2408dbcf02cSchristos 			fprintf(f, "%u\n", getpid());
2418dbcf02cSchristos 			fclose(f);
2428dbcf02cSchristos 		}
2438dbcf02cSchristos 	}
2448dbcf02cSchristos 
2458dbcf02cSchristos 	return -0;
246111b9fd8Schristos #endif /* defined(__uClinux__) || defined(__sun__) */
2478dbcf02cSchristos }
2488dbcf02cSchristos 
2498dbcf02cSchristos 
2508dbcf02cSchristos void os_daemonize_terminate(const char *pid_file)
2518dbcf02cSchristos {
2528dbcf02cSchristos 	if (pid_file)
2538dbcf02cSchristos 		unlink(pid_file);
2548dbcf02cSchristos }
2558dbcf02cSchristos 
2568dbcf02cSchristos 
2578dbcf02cSchristos int os_get_random(unsigned char *buf, size_t len)
2588dbcf02cSchristos {
259460bb4fcSchristos #ifdef TEST_FUZZ
260460bb4fcSchristos 	size_t i;
261460bb4fcSchristos 
262460bb4fcSchristos 	for (i = 0; i < len; i++)
263460bb4fcSchristos 		buf[i] = i & 0xff;
264460bb4fcSchristos 	return 0;
265460bb4fcSchristos #else /* TEST_FUZZ */
2668dbcf02cSchristos 	FILE *f;
2678dbcf02cSchristos 	size_t rc;
2688dbcf02cSchristos 
269ecc36642Schristos 	if (TEST_FAIL())
270ecc36642Schristos 		return -1;
271ecc36642Schristos 
2728dbcf02cSchristos 	f = fopen("/dev/urandom", "rb");
2738dbcf02cSchristos 	if (f == NULL) {
2748dbcf02cSchristos 		printf("Could not open /dev/urandom.\n");
2758dbcf02cSchristos 		return -1;
2768dbcf02cSchristos 	}
2778dbcf02cSchristos 
2788dbcf02cSchristos 	rc = fread(buf, 1, len, f);
2798dbcf02cSchristos 	fclose(f);
2808dbcf02cSchristos 
2818dbcf02cSchristos 	return rc != len ? -1 : 0;
282460bb4fcSchristos #endif /* TEST_FUZZ */
2838dbcf02cSchristos }
2848dbcf02cSchristos 
2858dbcf02cSchristos 
2868dbcf02cSchristos unsigned long os_random(void)
2878dbcf02cSchristos {
2888dbcf02cSchristos 	return random();
2898dbcf02cSchristos }
2908dbcf02cSchristos 
2918dbcf02cSchristos 
2928dbcf02cSchristos char * os_rel2abs_path(const char *rel_path)
2938dbcf02cSchristos {
2948dbcf02cSchristos 	char *buf = NULL, *cwd, *ret;
2958dbcf02cSchristos 	size_t len = 128, cwd_len, rel_len, ret_len;
2968dbcf02cSchristos 	int last_errno;
2978dbcf02cSchristos 
2983c260e60Schristos 	if (!rel_path)
2993c260e60Schristos 		return NULL;
3003c260e60Schristos 
3018dbcf02cSchristos 	if (rel_path[0] == '/')
3028dbcf02cSchristos 		return os_strdup(rel_path);
3038dbcf02cSchristos 
3048dbcf02cSchristos 	for (;;) {
3058dbcf02cSchristos 		buf = os_malloc(len);
3068dbcf02cSchristos 		if (buf == NULL)
3078dbcf02cSchristos 			return NULL;
3088dbcf02cSchristos 		cwd = getcwd(buf, len);
3098dbcf02cSchristos 		if (cwd == NULL) {
3108dbcf02cSchristos 			last_errno = errno;
3118dbcf02cSchristos 			os_free(buf);
3128dbcf02cSchristos 			if (last_errno != ERANGE)
3138dbcf02cSchristos 				return NULL;
3148dbcf02cSchristos 			len *= 2;
3158dbcf02cSchristos 			if (len > 2000)
3168dbcf02cSchristos 				return NULL;
3178dbcf02cSchristos 		} else {
3188dbcf02cSchristos 			buf[len - 1] = '\0';
3198dbcf02cSchristos 			break;
3208dbcf02cSchristos 		}
3218dbcf02cSchristos 	}
3228dbcf02cSchristos 
3238dbcf02cSchristos 	cwd_len = os_strlen(cwd);
3248dbcf02cSchristos 	rel_len = os_strlen(rel_path);
3258dbcf02cSchristos 	ret_len = cwd_len + 1 + rel_len + 1;
3268dbcf02cSchristos 	ret = os_malloc(ret_len);
3278dbcf02cSchristos 	if (ret) {
3288dbcf02cSchristos 		os_memcpy(ret, cwd, cwd_len);
3298dbcf02cSchristos 		ret[cwd_len] = '/';
3308dbcf02cSchristos 		os_memcpy(ret + cwd_len + 1, rel_path, rel_len);
3318dbcf02cSchristos 		ret[ret_len - 1] = '\0';
3328dbcf02cSchristos 	}
3338dbcf02cSchristos 	os_free(buf);
3348dbcf02cSchristos 	return ret;
3358dbcf02cSchristos }
3368dbcf02cSchristos 
3378dbcf02cSchristos 
3388dbcf02cSchristos int os_program_init(void)
3398dbcf02cSchristos {
340*45d3cc13Schristos 	unsigned int seed;
341*45d3cc13Schristos 
342111b9fd8Schristos #ifdef ANDROID
343111b9fd8Schristos 	/*
344111b9fd8Schristos 	 * We ignore errors here since errors are normal if we
345111b9fd8Schristos 	 * are already running as non-root.
346111b9fd8Schristos 	 */
3473c260e60Schristos #ifdef ANDROID_SETGROUPS_OVERRIDE
3483c260e60Schristos 	gid_t groups[] = { ANDROID_SETGROUPS_OVERRIDE };
3493c260e60Schristos #else /* ANDROID_SETGROUPS_OVERRIDE */
350111b9fd8Schristos 	gid_t groups[] = { AID_INET, AID_WIFI, AID_KEYSTORE };
3513c260e60Schristos #endif /* ANDROID_SETGROUPS_OVERRIDE */
352111b9fd8Schristos 	struct __user_cap_header_struct header;
353111b9fd8Schristos 	struct __user_cap_data_struct cap;
354111b9fd8Schristos 
3553c260e60Schristos 	setgroups(ARRAY_SIZE(groups), groups);
356111b9fd8Schristos 
357111b9fd8Schristos 	prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
358111b9fd8Schristos 
359111b9fd8Schristos 	setgid(AID_WIFI);
360111b9fd8Schristos 	setuid(AID_WIFI);
361111b9fd8Schristos 
362111b9fd8Schristos 	header.version = _LINUX_CAPABILITY_VERSION;
363111b9fd8Schristos 	header.pid = 0;
364111b9fd8Schristos 	cap.effective = cap.permitted =
365111b9fd8Schristos 		(1 << CAP_NET_ADMIN) | (1 << CAP_NET_RAW);
366111b9fd8Schristos 	cap.inheritable = 0;
367111b9fd8Schristos 	capset(&header, &cap);
368111b9fd8Schristos #endif /* ANDROID */
369111b9fd8Schristos 
370*45d3cc13Schristos 	if (os_get_random((unsigned char *) &seed, sizeof(seed)) == 0)
371*45d3cc13Schristos 		srandom(seed);
372*45d3cc13Schristos 
3738dbcf02cSchristos 	return 0;
3748dbcf02cSchristos }
3758dbcf02cSchristos 
3768dbcf02cSchristos 
3778dbcf02cSchristos void os_program_deinit(void)
3788dbcf02cSchristos {
3798dbcf02cSchristos #ifdef WPA_TRACE
3808dbcf02cSchristos 	struct os_alloc_trace *a;
3818dbcf02cSchristos 	unsigned long total = 0;
3828dbcf02cSchristos 	dl_list_for_each(a, &alloc_list, struct os_alloc_trace, list) {
3838dbcf02cSchristos 		total += a->len;
3848dbcf02cSchristos 		if (a->magic != ALLOC_MAGIC) {
3858dbcf02cSchristos 			wpa_printf(MSG_INFO, "MEMLEAK[%p]: invalid magic 0x%x "
3868dbcf02cSchristos 				   "len %lu",
3878dbcf02cSchristos 				   a, a->magic, (unsigned long) a->len);
3888dbcf02cSchristos 			continue;
3898dbcf02cSchristos 		}
3908dbcf02cSchristos 		wpa_printf(MSG_INFO, "MEMLEAK[%p]: len %lu",
3918dbcf02cSchristos 			   a, (unsigned long) a->len);
3928dbcf02cSchristos 		wpa_trace_dump("memleak", a);
3938dbcf02cSchristos 	}
3948dbcf02cSchristos 	if (total)
3958dbcf02cSchristos 		wpa_printf(MSG_INFO, "MEMLEAK: total %lu bytes",
3968dbcf02cSchristos 			   (unsigned long) total);
397ecc36642Schristos 	wpa_trace_deinit();
3988dbcf02cSchristos #endif /* WPA_TRACE */
3998dbcf02cSchristos }
4008dbcf02cSchristos 
4018dbcf02cSchristos 
4028dbcf02cSchristos int os_setenv(const char *name, const char *value, int overwrite)
4038dbcf02cSchristos {
4048dbcf02cSchristos 	return setenv(name, value, overwrite);
4058dbcf02cSchristos }
4068dbcf02cSchristos 
4078dbcf02cSchristos 
4088dbcf02cSchristos int os_unsetenv(const char *name)
4098dbcf02cSchristos {
4108dbcf02cSchristos #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || \
4118dbcf02cSchristos     defined(__OpenBSD__)
4128dbcf02cSchristos 	unsetenv(name);
4138dbcf02cSchristos 	return 0;
4148dbcf02cSchristos #else
4158dbcf02cSchristos 	return unsetenv(name);
4168dbcf02cSchristos #endif
4178dbcf02cSchristos }
4188dbcf02cSchristos 
4198dbcf02cSchristos 
4208dbcf02cSchristos char * os_readfile(const char *name, size_t *len)
4218dbcf02cSchristos {
4228dbcf02cSchristos 	FILE *f;
4238dbcf02cSchristos 	char *buf;
424111b9fd8Schristos 	long pos;
4258dbcf02cSchristos 
4268dbcf02cSchristos 	f = fopen(name, "rb");
4278dbcf02cSchristos 	if (f == NULL)
4288dbcf02cSchristos 		return NULL;
4298dbcf02cSchristos 
430111b9fd8Schristos 	if (fseek(f, 0, SEEK_END) < 0 || (pos = ftell(f)) < 0) {
431111b9fd8Schristos 		fclose(f);
432111b9fd8Schristos 		return NULL;
433111b9fd8Schristos 	}
434111b9fd8Schristos 	*len = pos;
435111b9fd8Schristos 	if (fseek(f, 0, SEEK_SET) < 0) {
436111b9fd8Schristos 		fclose(f);
437111b9fd8Schristos 		return NULL;
438111b9fd8Schristos 	}
4398dbcf02cSchristos 
4408dbcf02cSchristos 	buf = os_malloc(*len);
4418dbcf02cSchristos 	if (buf == NULL) {
4428dbcf02cSchristos 		fclose(f);
4438dbcf02cSchristos 		return NULL;
4448dbcf02cSchristos 	}
4458dbcf02cSchristos 
4468dbcf02cSchristos 	if (fread(buf, 1, *len, f) != *len) {
4478dbcf02cSchristos 		fclose(f);
4488dbcf02cSchristos 		os_free(buf);
4498dbcf02cSchristos 		return NULL;
4508dbcf02cSchristos 	}
4518dbcf02cSchristos 
4528dbcf02cSchristos 	fclose(f);
4538dbcf02cSchristos 
4548dbcf02cSchristos 	return buf;
4558dbcf02cSchristos }
4568dbcf02cSchristos 
4578dbcf02cSchristos 
4583c260e60Schristos int os_file_exists(const char *fname)
4593c260e60Schristos {
460ecc36642Schristos 	return access(fname, F_OK) == 0;
461ecc36642Schristos }
462ecc36642Schristos 
463ecc36642Schristos 
464ecc36642Schristos int os_fdatasync(FILE *stream)
465ecc36642Schristos {
466ecc36642Schristos 	if (!fflush(stream)) {
467*45d3cc13Schristos #if defined __FreeBSD__ || defined __linux__
468ecc36642Schristos 		return fdatasync(fileno(stream));
469*45d3cc13Schristos #else /* !__linux__ && !__FreeBSD__ */
470ecc36642Schristos #ifdef F_FULLFSYNC
471ecc36642Schristos 		/* OS X does not implement fdatasync(). */
472ecc36642Schristos 		return fcntl(fileno(stream), F_FULLFSYNC);
473ecc36642Schristos #else /* F_FULLFSYNC */
474ecc36642Schristos 		return fsync(fileno(stream));
475ecc36642Schristos #endif /* F_FULLFSYNC */
476ecc36642Schristos #endif /* __linux__ */
477ecc36642Schristos 	}
478ecc36642Schristos 
479ecc36642Schristos 	return -1;
4803c260e60Schristos }
4813c260e60Schristos 
4823c260e60Schristos 
4838dbcf02cSchristos #ifndef WPA_TRACE
4848dbcf02cSchristos void * os_zalloc(size_t size)
4858dbcf02cSchristos {
4868dbcf02cSchristos 	return calloc(1, size);
4878dbcf02cSchristos }
4888dbcf02cSchristos #endif /* WPA_TRACE */
4898dbcf02cSchristos 
4908dbcf02cSchristos 
4918dbcf02cSchristos size_t os_strlcpy(char *dest, const char *src, size_t siz)
4928dbcf02cSchristos {
4938dbcf02cSchristos 	const char *s = src;
4948dbcf02cSchristos 	size_t left = siz;
4958dbcf02cSchristos 
4968dbcf02cSchristos 	if (left) {
4978dbcf02cSchristos 		/* Copy string up to the maximum size of the dest buffer */
4988dbcf02cSchristos 		while (--left != 0) {
4998dbcf02cSchristos 			if ((*dest++ = *s++) == '\0')
5008dbcf02cSchristos 				break;
5018dbcf02cSchristos 		}
5028dbcf02cSchristos 	}
5038dbcf02cSchristos 
5048dbcf02cSchristos 	if (left == 0) {
5058dbcf02cSchristos 		/* Not enough room for the string; force NUL-termination */
5068dbcf02cSchristos 		if (siz != 0)
5078dbcf02cSchristos 			*dest = '\0';
5088dbcf02cSchristos 		while (*s++)
5098dbcf02cSchristos 			; /* determine total src string length */
5108dbcf02cSchristos 	}
5118dbcf02cSchristos 
5128dbcf02cSchristos 	return s - src - 1;
5138dbcf02cSchristos }
5148dbcf02cSchristos 
5158dbcf02cSchristos 
5163c260e60Schristos int os_memcmp_const(const void *a, const void *b, size_t len)
5173c260e60Schristos {
5183c260e60Schristos 	const u8 *aa = a;
5193c260e60Schristos 	const u8 *bb = b;
5203c260e60Schristos 	size_t i;
5213c260e60Schristos 	u8 res;
5223c260e60Schristos 
5233c260e60Schristos 	for (res = 0, i = 0; i < len; i++)
5243c260e60Schristos 		res |= aa[i] ^ bb[i];
5253c260e60Schristos 
5263c260e60Schristos 	return res;
5273c260e60Schristos }
5283c260e60Schristos 
5293c260e60Schristos 
530be6b3c4dSchristos void * os_memdup(const void *src, size_t len)
531be6b3c4dSchristos {
532be6b3c4dSchristos 	void *r = os_malloc(len);
533be6b3c4dSchristos 
534460bb4fcSchristos 	if (r && src)
535be6b3c4dSchristos 		os_memcpy(r, src, len);
536be6b3c4dSchristos 	return r;
537be6b3c4dSchristos }
538be6b3c4dSchristos 
539be6b3c4dSchristos 
5408dbcf02cSchristos #ifdef WPA_TRACE
5418dbcf02cSchristos 
542299bbf24Schristos #if defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS)
543*45d3cc13Schristos struct wpa_trace_test_fail {
544*45d3cc13Schristos 	unsigned int fail_after;
545*45d3cc13Schristos 	char pattern[256];
546*45d3cc13Schristos } wpa_trace_test_fail[5][2];
547299bbf24Schristos 
548*45d3cc13Schristos int testing_test_fail(const char *tag, bool is_alloc)
549299bbf24Schristos {
550*45d3cc13Schristos 	const char *ignore_list[] = {
551*45d3cc13Schristos 		"os_malloc", "os_zalloc", "os_calloc", "os_realloc",
552*45d3cc13Schristos 		"os_realloc_array", "os_strdup", "os_memdup"
553*45d3cc13Schristos 	};
554299bbf24Schristos 	const char *func[WPA_TRACE_LEN];
555*45d3cc13Schristos 	size_t i, j, res, len, idx;
556299bbf24Schristos 	char *pos, *next;
557299bbf24Schristos 	int match;
558299bbf24Schristos 
559*45d3cc13Schristos 	is_alloc = !!is_alloc;
560*45d3cc13Schristos 
561*45d3cc13Schristos 	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
562*45d3cc13Schristos 		if (wpa_trace_test_fail[is_alloc][idx].fail_after != 0)
563*45d3cc13Schristos 			break;
564*45d3cc13Schristos 	}
565*45d3cc13Schristos 	if (idx >= ARRAY_SIZE(wpa_trace_test_fail[is_alloc]))
566299bbf24Schristos 		return 0;
567299bbf24Schristos 
568299bbf24Schristos 	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
569299bbf24Schristos 	i = 0;
570*45d3cc13Schristos 
571*45d3cc13Schristos 	if (is_alloc) {
572*45d3cc13Schristos 		/* Skip our own stack frame */
573be6b3c4dSchristos 		i++;
574299bbf24Schristos 
575*45d3cc13Schristos 		/* Skip allocation helpers */
576*45d3cc13Schristos 		for (j = 0; j < ARRAY_SIZE(ignore_list) && i < res; j++) {
577*45d3cc13Schristos 			if (os_strcmp(func[i], ignore_list[j]) == 0)
578*45d3cc13Schristos 				i++;
579*45d3cc13Schristos 		}
580*45d3cc13Schristos 	} else {
581*45d3cc13Schristos 		/* Not allocation, we might have a tag, if so, replace our
582*45d3cc13Schristos 		 * own stack frame with the tag, otherwise skip it.
583*45d3cc13Schristos 		 */
584*45d3cc13Schristos 		if (tag)
585*45d3cc13Schristos 			func[0] = tag;
586*45d3cc13Schristos 		else
587*45d3cc13Schristos 			i++;
588*45d3cc13Schristos 	}
589*45d3cc13Schristos 
590*45d3cc13Schristos 	pos = wpa_trace_test_fail[is_alloc][idx].pattern;
591*45d3cc13Schristos 
592*45d3cc13Schristos 	/* The prefixes mean:
593*45d3cc13Schristos 	 * - '=': The function needs to be next in the backtrace
594*45d3cc13Schristos 	 * - '?': The function is optionally present in the backtrace
595*45d3cc13Schristos 	 */
596299bbf24Schristos 
597299bbf24Schristos 	match = 0;
598299bbf24Schristos 	while (i < res) {
599299bbf24Schristos 		int allow_skip = 1;
600299bbf24Schristos 		int maybe = 0;
601*45d3cc13Schristos 		bool prefix = false;
602299bbf24Schristos 
603299bbf24Schristos 		if (*pos == '=') {
604299bbf24Schristos 			allow_skip = 0;
605299bbf24Schristos 			pos++;
606299bbf24Schristos 		} else if (*pos == '?') {
607299bbf24Schristos 			maybe = 1;
608299bbf24Schristos 			pos++;
609299bbf24Schristos 		}
610299bbf24Schristos 		next = os_strchr(pos, ';');
611299bbf24Schristos 		if (next)
612299bbf24Schristos 			len = next - pos;
613299bbf24Schristos 		else
614299bbf24Schristos 			len = os_strlen(pos);
615*45d3cc13Schristos 		if (len >= 1 && pos[len - 1] == '*') {
616*45d3cc13Schristos 			prefix = true;
617*45d3cc13Schristos 			len -= 1;
618*45d3cc13Schristos 		}
619*45d3cc13Schristos 		if (os_strncmp(pos, func[i], len) != 0 ||
620*45d3cc13Schristos 		    (!prefix && func[i][len] != '\0')) {
621299bbf24Schristos 			if (maybe && next) {
622299bbf24Schristos 				pos = next + 1;
623299bbf24Schristos 				continue;
624299bbf24Schristos 			}
625299bbf24Schristos 			if (allow_skip) {
626299bbf24Schristos 				i++;
627299bbf24Schristos 				continue;
628299bbf24Schristos 			}
629299bbf24Schristos 			return 0;
630299bbf24Schristos 		}
631299bbf24Schristos 		if (!next) {
632299bbf24Schristos 			match = 1;
633299bbf24Schristos 			break;
634299bbf24Schristos 		}
635299bbf24Schristos 		pos = next + 1;
636299bbf24Schristos 		i++;
637299bbf24Schristos 	}
638299bbf24Schristos 	if (!match)
639299bbf24Schristos 		return 0;
640299bbf24Schristos 
641*45d3cc13Schristos 	wpa_trace_test_fail[is_alloc][idx].fail_after--;
642*45d3cc13Schristos 	if (wpa_trace_test_fail[is_alloc][idx].fail_after == 0) {
643ecc36642Schristos 		wpa_printf(MSG_INFO, "TESTING: fail at %s",
644*45d3cc13Schristos 			   wpa_trace_test_fail[is_alloc][idx].pattern);
645ecc36642Schristos 		for (i = 0; i < res; i++)
646ecc36642Schristos 			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
647ecc36642Schristos 				   (int) i, func[i]);
648ecc36642Schristos 		return 1;
649ecc36642Schristos 	}
650ecc36642Schristos 
651ecc36642Schristos 	return 0;
652ecc36642Schristos }
653ecc36642Schristos 
654299bbf24Schristos 
655*45d3cc13Schristos int testing_set_fail_pattern(bool is_alloc, char *patterns)
656*45d3cc13Schristos {
657*45d3cc13Schristos #ifdef WPA_TRACE_BFD
658*45d3cc13Schristos 	char *token, *context = NULL;
659*45d3cc13Schristos 	size_t idx;
660*45d3cc13Schristos 
661*45d3cc13Schristos 	is_alloc = !!is_alloc;
662*45d3cc13Schristos 
663*45d3cc13Schristos 	os_memset(wpa_trace_test_fail[is_alloc], 0,
664*45d3cc13Schristos 		  sizeof(wpa_trace_test_fail[is_alloc]));
665*45d3cc13Schristos 
666*45d3cc13Schristos 	idx = 0;
667*45d3cc13Schristos 	while ((token = str_token(patterns, " \n\r\t", &context)) &&
668*45d3cc13Schristos 	       idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc])) {
669*45d3cc13Schristos 		wpa_trace_test_fail[is_alloc][idx].fail_after = atoi(token);
670*45d3cc13Schristos 		token = os_strchr(token, ':');
671*45d3cc13Schristos 		if (!token) {
672*45d3cc13Schristos 			os_memset(wpa_trace_test_fail[is_alloc], 0,
673*45d3cc13Schristos 				  sizeof(wpa_trace_test_fail[is_alloc]));
674*45d3cc13Schristos 			return -1;
675*45d3cc13Schristos 		}
676*45d3cc13Schristos 
677*45d3cc13Schristos 		os_strlcpy(wpa_trace_test_fail[is_alloc][idx].pattern,
678*45d3cc13Schristos 			   token + 1,
679*45d3cc13Schristos 			   sizeof(wpa_trace_test_fail[is_alloc][0].pattern));
680*45d3cc13Schristos 		idx++;
681*45d3cc13Schristos 	}
682*45d3cc13Schristos 
683*45d3cc13Schristos 	return 0;
684*45d3cc13Schristos #else /* WPA_TRACE_BFD */
685*45d3cc13Schristos 	return -1;
686*45d3cc13Schristos #endif /* WPA_TRACE_BFD */
687*45d3cc13Schristos }
688*45d3cc13Schristos 
689*45d3cc13Schristos 
690*45d3cc13Schristos int testing_get_fail_pattern(bool is_alloc, char *buf, size_t buflen)
691*45d3cc13Schristos {
692*45d3cc13Schristos #ifdef WPA_TRACE_BFD
693*45d3cc13Schristos 	size_t idx, ret;
694*45d3cc13Schristos 	char *pos = buf;
695*45d3cc13Schristos 	char *end = buf + buflen;
696*45d3cc13Schristos 
697*45d3cc13Schristos 	is_alloc = !!is_alloc;
698*45d3cc13Schristos 
699*45d3cc13Schristos 	for (idx = 0; idx < ARRAY_SIZE(wpa_trace_test_fail[is_alloc]); idx++) {
700*45d3cc13Schristos 		if (wpa_trace_test_fail[is_alloc][idx].pattern[0] == '\0')
701*45d3cc13Schristos 			break;
702*45d3cc13Schristos 
703*45d3cc13Schristos 		ret = os_snprintf(pos, end - pos, "%s%u:%s",
704*45d3cc13Schristos 				  pos == buf ? "" : " ",
705*45d3cc13Schristos 				  wpa_trace_test_fail[is_alloc][idx].fail_after,
706*45d3cc13Schristos 				  wpa_trace_test_fail[is_alloc][idx].pattern);
707*45d3cc13Schristos 		if (os_snprintf_error(end - pos, ret))
708*45d3cc13Schristos 			break;
709*45d3cc13Schristos 		pos += ret;
710*45d3cc13Schristos 	}
711*45d3cc13Schristos 
712*45d3cc13Schristos 	return pos - buf;
713*45d3cc13Schristos #else /* WPA_TRACE_BFD */
714*45d3cc13Schristos 	return -1;
715*45d3cc13Schristos #endif /* WPA_TRACE_BFD */
716*45d3cc13Schristos }
717*45d3cc13Schristos 
718*45d3cc13Schristos #else /* defined(WPA_TRACE_BFD) && defined(CONFIG_TESTING_OPTIONS) */
719*45d3cc13Schristos 
720*45d3cc13Schristos static inline int testing_test_fail(const char *tag, bool is_alloc)
721299bbf24Schristos {
722299bbf24Schristos 	return 0;
723299bbf24Schristos }
724*45d3cc13Schristos 
725299bbf24Schristos #endif
726299bbf24Schristos 
7278dbcf02cSchristos void * os_malloc(size_t size)
7288dbcf02cSchristos {
7298dbcf02cSchristos 	struct os_alloc_trace *a;
730299bbf24Schristos 
731*45d3cc13Schristos 	if (testing_test_fail(NULL, true))
732299bbf24Schristos 		return NULL;
733299bbf24Schristos 
7348dbcf02cSchristos 	a = malloc(sizeof(*a) + size);
7358dbcf02cSchristos 	if (a == NULL)
7368dbcf02cSchristos 		return NULL;
7378dbcf02cSchristos 	a->magic = ALLOC_MAGIC;
7388dbcf02cSchristos 	dl_list_add(&alloc_list, &a->list);
7398dbcf02cSchristos 	a->len = size;
7408dbcf02cSchristos 	wpa_trace_record(a);
7418dbcf02cSchristos 	return a + 1;
7428dbcf02cSchristos }
7438dbcf02cSchristos 
7448dbcf02cSchristos 
7458dbcf02cSchristos void * os_realloc(void *ptr, size_t size)
7468dbcf02cSchristos {
7478dbcf02cSchristos 	struct os_alloc_trace *a;
7488dbcf02cSchristos 	size_t copy_len;
7498dbcf02cSchristos 	void *n;
7508dbcf02cSchristos 
7518dbcf02cSchristos 	if (ptr == NULL)
7528dbcf02cSchristos 		return os_malloc(size);
7538dbcf02cSchristos 
754e6e4448bSchristos 	a = (struct os_alloc_trace *) ptr - 1;
7558dbcf02cSchristos 	if (a->magic != ALLOC_MAGIC) {
7568dbcf02cSchristos 		wpa_printf(MSG_INFO, "REALLOC[%p]: invalid magic 0x%x%s",
7578dbcf02cSchristos 			   a, a->magic,
7588dbcf02cSchristos 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
7598dbcf02cSchristos 		wpa_trace_show("Invalid os_realloc() call");
7608dbcf02cSchristos 		abort();
7618dbcf02cSchristos 	}
7628dbcf02cSchristos 	n = os_malloc(size);
7638dbcf02cSchristos 	if (n == NULL)
7648dbcf02cSchristos 		return NULL;
7658dbcf02cSchristos 	copy_len = a->len;
7668dbcf02cSchristos 	if (copy_len > size)
7678dbcf02cSchristos 		copy_len = size;
7688dbcf02cSchristos 	os_memcpy(n, a + 1, copy_len);
7698dbcf02cSchristos 	os_free(ptr);
7708dbcf02cSchristos 	return n;
7718dbcf02cSchristos }
7728dbcf02cSchristos 
7738dbcf02cSchristos 
7748dbcf02cSchristos void os_free(void *ptr)
7758dbcf02cSchristos {
7768dbcf02cSchristos 	struct os_alloc_trace *a;
7778dbcf02cSchristos 
7788dbcf02cSchristos 	if (ptr == NULL)
7798dbcf02cSchristos 		return;
780e6e4448bSchristos 	a = (struct os_alloc_trace *) ptr - 1;
7818dbcf02cSchristos 	if (a->magic != ALLOC_MAGIC) {
7828dbcf02cSchristos 		wpa_printf(MSG_INFO, "FREE[%p]: invalid magic 0x%x%s",
7838dbcf02cSchristos 			   a, a->magic,
7848dbcf02cSchristos 			   a->magic == FREED_MAGIC ? " (already freed)" : "");
7858dbcf02cSchristos 		wpa_trace_show("Invalid os_free() call");
7868dbcf02cSchristos 		abort();
7878dbcf02cSchristos 	}
7888dbcf02cSchristos 	dl_list_del(&a->list);
7898dbcf02cSchristos 	a->magic = FREED_MAGIC;
7908dbcf02cSchristos 
7918dbcf02cSchristos 	wpa_trace_check_ref(ptr);
7928dbcf02cSchristos 	free(a);
7938dbcf02cSchristos }
7948dbcf02cSchristos 
7958dbcf02cSchristos 
7968dbcf02cSchristos void * os_zalloc(size_t size)
7978dbcf02cSchristos {
7988dbcf02cSchristos 	void *ptr = os_malloc(size);
7998dbcf02cSchristos 	if (ptr)
8008dbcf02cSchristos 		os_memset(ptr, 0, size);
8018dbcf02cSchristos 	return ptr;
8028dbcf02cSchristos }
8038dbcf02cSchristos 
8048dbcf02cSchristos 
8058dbcf02cSchristos char * os_strdup(const char *s)
8068dbcf02cSchristos {
8078dbcf02cSchristos 	size_t len;
8088dbcf02cSchristos 	char *d;
8098dbcf02cSchristos 	len = os_strlen(s);
8108dbcf02cSchristos 	d = os_malloc(len + 1);
8118dbcf02cSchristos 	if (d == NULL)
8128dbcf02cSchristos 		return NULL;
8138dbcf02cSchristos 	os_memcpy(d, s, len);
8148dbcf02cSchristos 	d[len] = '\0';
8158dbcf02cSchristos 	return d;
8168dbcf02cSchristos }
8178dbcf02cSchristos 
8188dbcf02cSchristos #endif /* WPA_TRACE */
8193c260e60Schristos 
8203c260e60Schristos 
8213c260e60Schristos int os_exec(const char *program, const char *arg, int wait_completion)
8223c260e60Schristos {
8233c260e60Schristos 	pid_t pid;
8243c260e60Schristos 	int pid_status;
8253c260e60Schristos 
8263c260e60Schristos 	pid = fork();
8273c260e60Schristos 	if (pid < 0) {
8283c260e60Schristos 		perror("fork");
8293c260e60Schristos 		return -1;
8303c260e60Schristos 	}
8313c260e60Schristos 
8323c260e60Schristos 	if (pid == 0) {
8333c260e60Schristos 		/* run the external command in the child process */
834fe1a092fSchristos #define MAX_ARG 30
8353c260e60Schristos 		char *_program, *_arg, *pos;
8363c260e60Schristos 		char *argv[MAX_ARG + 1];
8373c260e60Schristos 		int i;
8383c260e60Schristos 
8393c260e60Schristos 		_program = os_strdup(program);
8403c260e60Schristos 		_arg = os_strdup(arg);
8413c260e60Schristos 
8423c260e60Schristos 		argv[0] = _program;
8433c260e60Schristos 
8443c260e60Schristos 		i = 1;
8453c260e60Schristos 		pos = _arg;
8463c260e60Schristos 		while (i < MAX_ARG && pos && *pos) {
8473c260e60Schristos 			while (*pos == ' ')
8483c260e60Schristos 				pos++;
8493c260e60Schristos 			if (*pos == '\0')
8503c260e60Schristos 				break;
8513c260e60Schristos 			argv[i++] = pos;
8523c260e60Schristos 			pos = os_strchr(pos, ' ');
8533c260e60Schristos 			if (pos)
8543c260e60Schristos 				*pos++ = '\0';
8553c260e60Schristos 		}
8563c260e60Schristos 		argv[i] = NULL;
8573c260e60Schristos 
8583c260e60Schristos 		execv(program, argv);
8593c260e60Schristos 		perror("execv");
8603c260e60Schristos 		os_free(_program);
8613c260e60Schristos 		os_free(_arg);
8623c260e60Schristos 		exit(0);
8633c260e60Schristos 		return -1;
8643c260e60Schristos 	}
8653c260e60Schristos 
8663c260e60Schristos 	if (wait_completion) {
8673c260e60Schristos 		/* wait for the child process to complete in the parent */
8683c260e60Schristos 		waitpid(pid, &pid_status, 0);
8693c260e60Schristos 	}
8703c260e60Schristos 
8713c260e60Schristos 	return 0;
8723c260e60Schristos }
873