16cd6a6acSopenharmony_ci/* Author: Trusted Computer Solutions, Inc.
26cd6a6acSopenharmony_ci *
36cd6a6acSopenharmony_ci * Modified:
46cd6a6acSopenharmony_ci * Yuichi Nakamura <ynakam@hitachisoft.jp>
56cd6a6acSopenharmony_ci - Stubs are used when DISABLE_SETRANS is defined,
66cd6a6acSopenharmony_ci   it is to reduce size for such as embedded devices.
76cd6a6acSopenharmony_ci*/
86cd6a6acSopenharmony_ci
96cd6a6acSopenharmony_ci#include <sys/types.h>
106cd6a6acSopenharmony_ci#include <sys/socket.h>
116cd6a6acSopenharmony_ci#include <sys/un.h>
126cd6a6acSopenharmony_ci
136cd6a6acSopenharmony_ci#include <errno.h>
146cd6a6acSopenharmony_ci#include <stdlib.h>
156cd6a6acSopenharmony_ci#include <netdb.h>
166cd6a6acSopenharmony_ci#include <fcntl.h>
176cd6a6acSopenharmony_ci#include <stdio.h>
186cd6a6acSopenharmony_ci#include <string.h>
196cd6a6acSopenharmony_ci#include <ctype.h>
206cd6a6acSopenharmony_ci#include <unistd.h>
216cd6a6acSopenharmony_ci#include <sys/uio.h>
226cd6a6acSopenharmony_ci#include "selinux_internal.h"
236cd6a6acSopenharmony_ci#include "setrans_internal.h"
246cd6a6acSopenharmony_ci
256cd6a6acSopenharmony_ci#ifndef DISABLE_SETRANS
266cd6a6acSopenharmony_cistatic unsigned char has_setrans;
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci// Simple cache
296cd6a6acSopenharmony_cistatic __thread char * prev_t2r_trans = NULL;
306cd6a6acSopenharmony_cistatic __thread char * prev_t2r_raw = NULL;
316cd6a6acSopenharmony_cistatic __thread char * prev_r2t_trans = NULL;
326cd6a6acSopenharmony_cistatic __thread char * prev_r2t_raw = NULL;
336cd6a6acSopenharmony_cistatic __thread char *prev_r2c_trans = NULL;
346cd6a6acSopenharmony_cistatic __thread char * prev_r2c_raw = NULL;
356cd6a6acSopenharmony_ci
366cd6a6acSopenharmony_cistatic pthread_once_t once = PTHREAD_ONCE_INIT;
376cd6a6acSopenharmony_cistatic pthread_key_t destructor_key;
386cd6a6acSopenharmony_cistatic int destructor_key_initialized = 0;
396cd6a6acSopenharmony_cistatic __thread char destructor_initialized;
406cd6a6acSopenharmony_ci
416cd6a6acSopenharmony_ci/*
426cd6a6acSopenharmony_ci * setransd_open
436cd6a6acSopenharmony_ci *
446cd6a6acSopenharmony_ci * This function opens a socket to the setransd.
456cd6a6acSopenharmony_ci * Returns:  on success, a file descriptor ( >= 0 ) to the socket
466cd6a6acSopenharmony_ci *           on error, a negative value
476cd6a6acSopenharmony_ci */
486cd6a6acSopenharmony_cistatic int setransd_open(void)
496cd6a6acSopenharmony_ci{
506cd6a6acSopenharmony_ci	struct sockaddr_un addr;
516cd6a6acSopenharmony_ci	int fd;
526cd6a6acSopenharmony_ci#ifdef SOCK_CLOEXEC
536cd6a6acSopenharmony_ci	fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
546cd6a6acSopenharmony_ci	if (fd < 0 && errno == EINVAL)
556cd6a6acSopenharmony_ci#endif
566cd6a6acSopenharmony_ci	{
576cd6a6acSopenharmony_ci		fd = socket(PF_UNIX, SOCK_STREAM, 0);
586cd6a6acSopenharmony_ci		if (fd >= 0)
596cd6a6acSopenharmony_ci			if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
606cd6a6acSopenharmony_ci				close(fd);
616cd6a6acSopenharmony_ci				return -1;
626cd6a6acSopenharmony_ci			}
636cd6a6acSopenharmony_ci	}
646cd6a6acSopenharmony_ci	if (fd < 0)
656cd6a6acSopenharmony_ci		return -1;
666cd6a6acSopenharmony_ci
676cd6a6acSopenharmony_ci	memset(&addr, 0, sizeof(addr));
686cd6a6acSopenharmony_ci	addr.sun_family = AF_UNIX;
696cd6a6acSopenharmony_ci
706cd6a6acSopenharmony_ci	if (strlcpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
716cd6a6acSopenharmony_ci		close(fd);
726cd6a6acSopenharmony_ci		errno = EOVERFLOW;
736cd6a6acSopenharmony_ci		return -1;
746cd6a6acSopenharmony_ci	}
756cd6a6acSopenharmony_ci
766cd6a6acSopenharmony_ci	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
776cd6a6acSopenharmony_ci		close(fd);
786cd6a6acSopenharmony_ci		return -1;
796cd6a6acSopenharmony_ci	}
806cd6a6acSopenharmony_ci
816cd6a6acSopenharmony_ci	return fd;
826cd6a6acSopenharmony_ci}
836cd6a6acSopenharmony_ci
846cd6a6acSopenharmony_ci/* Returns: 0 on success, <0 on failure */
856cd6a6acSopenharmony_cistatic int
866cd6a6acSopenharmony_cisend_request(int fd, uint32_t function, const char *data1, const char *data2)
876cd6a6acSopenharmony_ci{
886cd6a6acSopenharmony_ci	struct msghdr msgh;
896cd6a6acSopenharmony_ci	struct iovec iov[5];
906cd6a6acSopenharmony_ci	uint32_t data1_size;
916cd6a6acSopenharmony_ci	uint32_t data2_size;
926cd6a6acSopenharmony_ci	ssize_t count, expected;
936cd6a6acSopenharmony_ci	unsigned int i;
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_ci	if (fd < 0)
966cd6a6acSopenharmony_ci		return -1;
976cd6a6acSopenharmony_ci
986cd6a6acSopenharmony_ci	if (!data1)
996cd6a6acSopenharmony_ci		data1 = "";
1006cd6a6acSopenharmony_ci	if (!data2)
1016cd6a6acSopenharmony_ci		data2 = "";
1026cd6a6acSopenharmony_ci
1036cd6a6acSopenharmony_ci	data1_size = strlen(data1) + 1;
1046cd6a6acSopenharmony_ci	data2_size = strlen(data2) + 1;
1056cd6a6acSopenharmony_ci
1066cd6a6acSopenharmony_ci	iov[0].iov_base = &function;
1076cd6a6acSopenharmony_ci	iov[0].iov_len = sizeof(function);
1086cd6a6acSopenharmony_ci	iov[1].iov_base = &data1_size;
1096cd6a6acSopenharmony_ci	iov[1].iov_len = sizeof(data1_size);
1106cd6a6acSopenharmony_ci	iov[2].iov_base = &data2_size;
1116cd6a6acSopenharmony_ci	iov[2].iov_len = sizeof(data2_size);
1126cd6a6acSopenharmony_ci	iov[3].iov_base = (char *)data1;
1136cd6a6acSopenharmony_ci	iov[3].iov_len = data1_size;
1146cd6a6acSopenharmony_ci	iov[4].iov_base = (char *)data2;
1156cd6a6acSopenharmony_ci	iov[4].iov_len = data2_size;
1166cd6a6acSopenharmony_ci	memset(&msgh, 0, sizeof(msgh));
1176cd6a6acSopenharmony_ci	msgh.msg_iov = iov;
1186cd6a6acSopenharmony_ci	msgh.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
1196cd6a6acSopenharmony_ci
1206cd6a6acSopenharmony_ci	expected = 0;
1216cd6a6acSopenharmony_ci	for (i = 0; i < sizeof(iov) / sizeof(iov[0]); i++)
1226cd6a6acSopenharmony_ci		expected += iov[i].iov_len;
1236cd6a6acSopenharmony_ci
1246cd6a6acSopenharmony_ci	while (((count = sendmsg(fd, &msgh, MSG_NOSIGNAL)) < 0)
1256cd6a6acSopenharmony_ci	       && (errno == EINTR)) ;
1266cd6a6acSopenharmony_ci	if (count < 0 || count != expected)
1276cd6a6acSopenharmony_ci		return -1;
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	return 0;
1306cd6a6acSopenharmony_ci}
1316cd6a6acSopenharmony_ci
1326cd6a6acSopenharmony_ci/* Returns: 0 on success, <0 on failure */
1336cd6a6acSopenharmony_cistatic int
1346cd6a6acSopenharmony_cireceive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val)
1356cd6a6acSopenharmony_ci{
1366cd6a6acSopenharmony_ci	struct iovec resp_hdr[3];
1376cd6a6acSopenharmony_ci	uint32_t func;
1386cd6a6acSopenharmony_ci	uint32_t data_size;
1396cd6a6acSopenharmony_ci	char *data;
1406cd6a6acSopenharmony_ci	struct iovec resp_data;
1416cd6a6acSopenharmony_ci	ssize_t count;
1426cd6a6acSopenharmony_ci
1436cd6a6acSopenharmony_ci	if (fd < 0)
1446cd6a6acSopenharmony_ci		return -1;
1456cd6a6acSopenharmony_ci
1466cd6a6acSopenharmony_ci	resp_hdr[0].iov_base = &func;
1476cd6a6acSopenharmony_ci	resp_hdr[0].iov_len = sizeof(func);
1486cd6a6acSopenharmony_ci	resp_hdr[1].iov_base = &data_size;
1496cd6a6acSopenharmony_ci	resp_hdr[1].iov_len = sizeof(data_size);
1506cd6a6acSopenharmony_ci	resp_hdr[2].iov_base = ret_val;
1516cd6a6acSopenharmony_ci	resp_hdr[2].iov_len = sizeof(*ret_val);
1526cd6a6acSopenharmony_ci
1536cd6a6acSopenharmony_ci	while (((count = readv(fd, resp_hdr, 3)) < 0) && (errno == EINTR)) ;
1546cd6a6acSopenharmony_ci	if (count != (sizeof(func) + sizeof(data_size) + sizeof(*ret_val))) {
1556cd6a6acSopenharmony_ci		return -1;
1566cd6a6acSopenharmony_ci	}
1576cd6a6acSopenharmony_ci
1586cd6a6acSopenharmony_ci	if (func != function || !data_size || data_size > MAX_DATA_BUF) {
1596cd6a6acSopenharmony_ci		return -1;
1606cd6a6acSopenharmony_ci	}
1616cd6a6acSopenharmony_ci
1626cd6a6acSopenharmony_ci	data = malloc(data_size);
1636cd6a6acSopenharmony_ci	if (!data)
1646cd6a6acSopenharmony_ci		return -1;
1656cd6a6acSopenharmony_ci	/* coveriety doesn't realize that data will be initialized in readv */
1666cd6a6acSopenharmony_ci	memset(data, 0, data_size);
1676cd6a6acSopenharmony_ci
1686cd6a6acSopenharmony_ci	resp_data.iov_base = data;
1696cd6a6acSopenharmony_ci	resp_data.iov_len = data_size;
1706cd6a6acSopenharmony_ci
1716cd6a6acSopenharmony_ci	while (((count = readv(fd, &resp_data, 1))) < 0 && (errno == EINTR)) ;
1726cd6a6acSopenharmony_ci	if (count < 0 || (uint32_t) count != data_size ||
1736cd6a6acSopenharmony_ci	    data[data_size - 1] != '\0') {
1746cd6a6acSopenharmony_ci		free(data);
1756cd6a6acSopenharmony_ci		return -1;
1766cd6a6acSopenharmony_ci	}
1776cd6a6acSopenharmony_ci	*outdata = data;
1786cd6a6acSopenharmony_ci	return 0;
1796cd6a6acSopenharmony_ci}
1806cd6a6acSopenharmony_ci
1816cd6a6acSopenharmony_cistatic int raw_to_trans_context(const char *raw, char **transp)
1826cd6a6acSopenharmony_ci{
1836cd6a6acSopenharmony_ci	int ret;
1846cd6a6acSopenharmony_ci	int32_t ret_val;
1856cd6a6acSopenharmony_ci	int fd;
1866cd6a6acSopenharmony_ci
1876cd6a6acSopenharmony_ci	*transp = NULL;
1886cd6a6acSopenharmony_ci
1896cd6a6acSopenharmony_ci	fd = setransd_open();
1906cd6a6acSopenharmony_ci	if (fd < 0)
1916cd6a6acSopenharmony_ci		return fd;
1926cd6a6acSopenharmony_ci
1936cd6a6acSopenharmony_ci	ret = send_request(fd, RAW_TO_TRANS_CONTEXT, raw, NULL);
1946cd6a6acSopenharmony_ci	if (ret)
1956cd6a6acSopenharmony_ci		goto out;
1966cd6a6acSopenharmony_ci
1976cd6a6acSopenharmony_ci	ret = receive_response(fd, RAW_TO_TRANS_CONTEXT, transp, &ret_val);
1986cd6a6acSopenharmony_ci	if (ret)
1996cd6a6acSopenharmony_ci		goto out;
2006cd6a6acSopenharmony_ci
2016cd6a6acSopenharmony_ci	ret = ret_val;
2026cd6a6acSopenharmony_ci      out:
2036cd6a6acSopenharmony_ci	close(fd);
2046cd6a6acSopenharmony_ci	return ret;
2056cd6a6acSopenharmony_ci}
2066cd6a6acSopenharmony_ci
2076cd6a6acSopenharmony_cistatic int trans_to_raw_context(const char *trans, char **rawp)
2086cd6a6acSopenharmony_ci{
2096cd6a6acSopenharmony_ci	int ret;
2106cd6a6acSopenharmony_ci	int32_t ret_val;
2116cd6a6acSopenharmony_ci	int fd;
2126cd6a6acSopenharmony_ci
2136cd6a6acSopenharmony_ci	*rawp = NULL;
2146cd6a6acSopenharmony_ci
2156cd6a6acSopenharmony_ci	fd = setransd_open();
2166cd6a6acSopenharmony_ci	if (fd < 0)
2176cd6a6acSopenharmony_ci		return fd;
2186cd6a6acSopenharmony_ci	ret = send_request(fd, TRANS_TO_RAW_CONTEXT, trans, NULL);
2196cd6a6acSopenharmony_ci	if (ret)
2206cd6a6acSopenharmony_ci		goto out;
2216cd6a6acSopenharmony_ci
2226cd6a6acSopenharmony_ci	ret = receive_response(fd, TRANS_TO_RAW_CONTEXT, rawp, &ret_val);
2236cd6a6acSopenharmony_ci	if (ret)
2246cd6a6acSopenharmony_ci		goto out;
2256cd6a6acSopenharmony_ci
2266cd6a6acSopenharmony_ci	ret = ret_val;
2276cd6a6acSopenharmony_ci      out:
2286cd6a6acSopenharmony_ci	close(fd);
2296cd6a6acSopenharmony_ci	return ret;
2306cd6a6acSopenharmony_ci}
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_cistatic int raw_context_to_color(const char *raw, char **colors)
2336cd6a6acSopenharmony_ci{
2346cd6a6acSopenharmony_ci	int ret;
2356cd6a6acSopenharmony_ci	int32_t ret_val;
2366cd6a6acSopenharmony_ci	int fd;
2376cd6a6acSopenharmony_ci
2386cd6a6acSopenharmony_ci	fd = setransd_open();
2396cd6a6acSopenharmony_ci	if (fd < 0)
2406cd6a6acSopenharmony_ci		return fd;
2416cd6a6acSopenharmony_ci
2426cd6a6acSopenharmony_ci	ret = send_request(fd, RAW_CONTEXT_TO_COLOR, raw, NULL);
2436cd6a6acSopenharmony_ci	if (ret)
2446cd6a6acSopenharmony_ci		goto out;
2456cd6a6acSopenharmony_ci
2466cd6a6acSopenharmony_ci	ret = receive_response(fd, RAW_CONTEXT_TO_COLOR, colors, &ret_val);
2476cd6a6acSopenharmony_ci	if (ret)
2486cd6a6acSopenharmony_ci		goto out;
2496cd6a6acSopenharmony_ci
2506cd6a6acSopenharmony_ci	ret = ret_val;
2516cd6a6acSopenharmony_ciout:
2526cd6a6acSopenharmony_ci	close(fd);
2536cd6a6acSopenharmony_ci	return ret;
2546cd6a6acSopenharmony_ci}
2556cd6a6acSopenharmony_ci
2566cd6a6acSopenharmony_cistatic void setrans_thread_destructor(void __attribute__((unused)) *unused)
2576cd6a6acSopenharmony_ci{
2586cd6a6acSopenharmony_ci	free(prev_t2r_trans);
2596cd6a6acSopenharmony_ci	free(prev_t2r_raw);
2606cd6a6acSopenharmony_ci	free(prev_r2t_trans);
2616cd6a6acSopenharmony_ci	free(prev_r2t_raw);
2626cd6a6acSopenharmony_ci	free(prev_r2c_trans);
2636cd6a6acSopenharmony_ci	free(prev_r2c_raw);
2646cd6a6acSopenharmony_ci}
2656cd6a6acSopenharmony_ci
2666cd6a6acSopenharmony_civoid __attribute__((destructor)) setrans_lib_destructor(void);
2676cd6a6acSopenharmony_ci
2686cd6a6acSopenharmony_civoid  __attribute__((destructor)) setrans_lib_destructor(void)
2696cd6a6acSopenharmony_ci{
2706cd6a6acSopenharmony_ci	if (!has_setrans)
2716cd6a6acSopenharmony_ci		return;
2726cd6a6acSopenharmony_ci	if (destructor_key_initialized)
2736cd6a6acSopenharmony_ci		__selinux_key_delete(destructor_key);
2746cd6a6acSopenharmony_ci}
2756cd6a6acSopenharmony_ci
2766cd6a6acSopenharmony_cistatic inline void init_thread_destructor(void)
2776cd6a6acSopenharmony_ci{
2786cd6a6acSopenharmony_ci	if (!has_setrans)
2796cd6a6acSopenharmony_ci		return;
2806cd6a6acSopenharmony_ci	if (destructor_initialized == 0) {
2816cd6a6acSopenharmony_ci		__selinux_setspecific(destructor_key, /* some valid address to please GCC */ &selinux_page_size);
2826cd6a6acSopenharmony_ci		destructor_initialized = 1;
2836cd6a6acSopenharmony_ci	}
2846cd6a6acSopenharmony_ci}
2856cd6a6acSopenharmony_ci
2866cd6a6acSopenharmony_cistatic void init_context_translations(void)
2876cd6a6acSopenharmony_ci{
2886cd6a6acSopenharmony_ci	has_setrans = (access(SETRANS_UNIX_SOCKET, F_OK) == 0);
2896cd6a6acSopenharmony_ci	if (!has_setrans)
2906cd6a6acSopenharmony_ci		return;
2916cd6a6acSopenharmony_ci	if (__selinux_key_create(&destructor_key, setrans_thread_destructor) == 0)
2926cd6a6acSopenharmony_ci		destructor_key_initialized = 1;
2936cd6a6acSopenharmony_ci}
2946cd6a6acSopenharmony_ci
2956cd6a6acSopenharmony_ciint selinux_trans_to_raw_context(const char * trans,
2966cd6a6acSopenharmony_ci				 char ** rawp)
2976cd6a6acSopenharmony_ci{
2986cd6a6acSopenharmony_ci	if (!trans) {
2996cd6a6acSopenharmony_ci		*rawp = NULL;
3006cd6a6acSopenharmony_ci		return 0;
3016cd6a6acSopenharmony_ci	}
3026cd6a6acSopenharmony_ci
3036cd6a6acSopenharmony_ci	__selinux_once(once, init_context_translations);
3046cd6a6acSopenharmony_ci	init_thread_destructor();
3056cd6a6acSopenharmony_ci
3066cd6a6acSopenharmony_ci	if (!has_setrans) {
3076cd6a6acSopenharmony_ci		*rawp = strdup(trans);
3086cd6a6acSopenharmony_ci		goto out;
3096cd6a6acSopenharmony_ci	}
3106cd6a6acSopenharmony_ci
3116cd6a6acSopenharmony_ci	if (prev_t2r_trans && strcmp(prev_t2r_trans, trans) == 0) {
3126cd6a6acSopenharmony_ci		*rawp = strdup(prev_t2r_raw);
3136cd6a6acSopenharmony_ci	} else {
3146cd6a6acSopenharmony_ci		free(prev_t2r_trans);
3156cd6a6acSopenharmony_ci		prev_t2r_trans = NULL;
3166cd6a6acSopenharmony_ci		free(prev_t2r_raw);
3176cd6a6acSopenharmony_ci		prev_t2r_raw = NULL;
3186cd6a6acSopenharmony_ci		if (trans_to_raw_context(trans, rawp))
3196cd6a6acSopenharmony_ci			*rawp = strdup(trans);
3206cd6a6acSopenharmony_ci		if (*rawp) {
3216cd6a6acSopenharmony_ci			prev_t2r_trans = strdup(trans);
3226cd6a6acSopenharmony_ci			if (!prev_t2r_trans)
3236cd6a6acSopenharmony_ci				goto out;
3246cd6a6acSopenharmony_ci			prev_t2r_raw = strdup(*rawp);
3256cd6a6acSopenharmony_ci			if (!prev_t2r_raw) {
3266cd6a6acSopenharmony_ci				free(prev_t2r_trans);
3276cd6a6acSopenharmony_ci				prev_t2r_trans = NULL;
3286cd6a6acSopenharmony_ci			}
3296cd6a6acSopenharmony_ci		}
3306cd6a6acSopenharmony_ci	}
3316cd6a6acSopenharmony_ci      out:
3326cd6a6acSopenharmony_ci	return *rawp ? 0 : -1;
3336cd6a6acSopenharmony_ci}
3346cd6a6acSopenharmony_ci
3356cd6a6acSopenharmony_ci
3366cd6a6acSopenharmony_ciint selinux_raw_to_trans_context(const char * raw,
3376cd6a6acSopenharmony_ci				 char ** transp)
3386cd6a6acSopenharmony_ci{
3396cd6a6acSopenharmony_ci	if (!raw) {
3406cd6a6acSopenharmony_ci		*transp = NULL;
3416cd6a6acSopenharmony_ci		return 0;
3426cd6a6acSopenharmony_ci	}
3436cd6a6acSopenharmony_ci
3446cd6a6acSopenharmony_ci	__selinux_once(once, init_context_translations);
3456cd6a6acSopenharmony_ci	init_thread_destructor();
3466cd6a6acSopenharmony_ci
3476cd6a6acSopenharmony_ci	if (!has_setrans)  {
3486cd6a6acSopenharmony_ci		*transp = strdup(raw);
3496cd6a6acSopenharmony_ci		goto out;
3506cd6a6acSopenharmony_ci	}
3516cd6a6acSopenharmony_ci
3526cd6a6acSopenharmony_ci	if (prev_r2t_raw && strcmp(prev_r2t_raw, raw) == 0) {
3536cd6a6acSopenharmony_ci		*transp = strdup(prev_r2t_trans);
3546cd6a6acSopenharmony_ci	} else {
3556cd6a6acSopenharmony_ci		free(prev_r2t_raw);
3566cd6a6acSopenharmony_ci		prev_r2t_raw = NULL;
3576cd6a6acSopenharmony_ci		free(prev_r2t_trans);
3586cd6a6acSopenharmony_ci		prev_r2t_trans = NULL;
3596cd6a6acSopenharmony_ci		if (raw_to_trans_context(raw, transp))
3606cd6a6acSopenharmony_ci			*transp = strdup(raw);
3616cd6a6acSopenharmony_ci		if (*transp) {
3626cd6a6acSopenharmony_ci			prev_r2t_raw = strdup(raw);
3636cd6a6acSopenharmony_ci			if (!prev_r2t_raw)
3646cd6a6acSopenharmony_ci				goto out;
3656cd6a6acSopenharmony_ci			prev_r2t_trans = strdup(*transp);
3666cd6a6acSopenharmony_ci			if (!prev_r2t_trans) {
3676cd6a6acSopenharmony_ci				free(prev_r2t_raw);
3686cd6a6acSopenharmony_ci				prev_r2t_raw = NULL;
3696cd6a6acSopenharmony_ci			}
3706cd6a6acSopenharmony_ci		}
3716cd6a6acSopenharmony_ci	}
3726cd6a6acSopenharmony_ci      out:
3736cd6a6acSopenharmony_ci	return *transp ? 0 : -1;
3746cd6a6acSopenharmony_ci}
3756cd6a6acSopenharmony_ci
3766cd6a6acSopenharmony_ci
3776cd6a6acSopenharmony_ciint selinux_raw_context_to_color(const char * raw, char **transp)
3786cd6a6acSopenharmony_ci{
3796cd6a6acSopenharmony_ci	if (!raw) {
3806cd6a6acSopenharmony_ci		*transp = NULL;
3816cd6a6acSopenharmony_ci		return -1;
3826cd6a6acSopenharmony_ci	}
3836cd6a6acSopenharmony_ci
3846cd6a6acSopenharmony_ci	__selinux_once(once, init_context_translations);
3856cd6a6acSopenharmony_ci	init_thread_destructor();
3866cd6a6acSopenharmony_ci
3876cd6a6acSopenharmony_ci	if (!has_setrans) {
3886cd6a6acSopenharmony_ci		*transp = strdup(raw);
3896cd6a6acSopenharmony_ci		goto out;
3906cd6a6acSopenharmony_ci	}
3916cd6a6acSopenharmony_ci
3926cd6a6acSopenharmony_ci	if (prev_r2c_raw && strcmp(prev_r2c_raw, raw) == 0) {
3936cd6a6acSopenharmony_ci		*transp = strdup(prev_r2c_trans);
3946cd6a6acSopenharmony_ci	} else {
3956cd6a6acSopenharmony_ci		free(prev_r2c_raw);
3966cd6a6acSopenharmony_ci		prev_r2c_raw = NULL;
3976cd6a6acSopenharmony_ci		free(prev_r2c_trans);
3986cd6a6acSopenharmony_ci		prev_r2c_trans = NULL;
3996cd6a6acSopenharmony_ci		if (raw_context_to_color(raw, transp))
4006cd6a6acSopenharmony_ci			return -1;
4016cd6a6acSopenharmony_ci		if (*transp) {
4026cd6a6acSopenharmony_ci			prev_r2c_raw = strdup(raw);
4036cd6a6acSopenharmony_ci			if (!prev_r2c_raw)
4046cd6a6acSopenharmony_ci				goto out;
4056cd6a6acSopenharmony_ci			prev_r2c_trans = strdup(*transp);
4066cd6a6acSopenharmony_ci			if (!prev_r2c_trans) {
4076cd6a6acSopenharmony_ci				free(prev_r2c_raw);
4086cd6a6acSopenharmony_ci				prev_r2c_raw = NULL;
4096cd6a6acSopenharmony_ci			}
4106cd6a6acSopenharmony_ci		}
4116cd6a6acSopenharmony_ci	}
4126cd6a6acSopenharmony_ci      out:
4136cd6a6acSopenharmony_ci	return *transp ? 0 : -1;
4146cd6a6acSopenharmony_ci}
4156cd6a6acSopenharmony_ci
4166cd6a6acSopenharmony_ci#else /*DISABLE_SETRANS*/
4176cd6a6acSopenharmony_ci
4186cd6a6acSopenharmony_ciint selinux_trans_to_raw_context(const char * trans,
4196cd6a6acSopenharmony_ci				 char ** rawp)
4206cd6a6acSopenharmony_ci{
4216cd6a6acSopenharmony_ci	if (!trans) {
4226cd6a6acSopenharmony_ci		*rawp = NULL;
4236cd6a6acSopenharmony_ci		return 0;
4246cd6a6acSopenharmony_ci	}
4256cd6a6acSopenharmony_ci
4266cd6a6acSopenharmony_ci	*rawp = strdup(trans);
4276cd6a6acSopenharmony_ci
4286cd6a6acSopenharmony_ci	return *rawp ? 0 : -1;
4296cd6a6acSopenharmony_ci}
4306cd6a6acSopenharmony_ci
4316cd6a6acSopenharmony_ci
4326cd6a6acSopenharmony_ciint selinux_raw_to_trans_context(const char * raw,
4336cd6a6acSopenharmony_ci				 char ** transp)
4346cd6a6acSopenharmony_ci{
4356cd6a6acSopenharmony_ci	if (!raw) {
4366cd6a6acSopenharmony_ci		*transp = NULL;
4376cd6a6acSopenharmony_ci		return 0;
4386cd6a6acSopenharmony_ci	}
4396cd6a6acSopenharmony_ci	*transp = strdup(raw);
4406cd6a6acSopenharmony_ci
4416cd6a6acSopenharmony_ci	return *transp ? 0 : -1;
4426cd6a6acSopenharmony_ci}
4436cd6a6acSopenharmony_ci
4446cd6a6acSopenharmony_ci#endif /*DISABLE_SETRANS*/
445