113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Author: Trusted Computer Solutions, Inc.
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Modified:
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Yuichi Nakamura <ynakam@hitachisoft.jp>
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle - Stubs are used when DISABLE_SETRANS is defined,
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle   it is to reduce size for such as embedded devices.
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle*/
813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/socket.h>
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/un.h>
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
1413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <netdb.h>
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <fcntl.h>
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <ctype.h>
2013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <unistd.h>
2113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "dso.h"
2213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "selinux_internal.h"
2313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "setrans_internal.h"
2413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#ifndef DISABLE_SETRANS
26a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalleystatic unsigned char has_setrans;
2713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle// Simple cache
299eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_t2r_trans = NULL;
309eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_t2r_raw = NULL;
319eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_r2t_trans = NULL;
329eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_r2t_raw = NULL;
331ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalleystatic __thread char *prev_r2c_trans = NULL;
349eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleystatic __thread char * prev_r2c_raw = NULL;
3513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
368c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalleystatic pthread_once_t once = PTHREAD_ONCE_INIT;
37a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walshstatic pthread_key_t destructor_key;
381629d2f89a8c5f758413b87b94740aaaa5f21144Daniel J Walshstatic int destructor_key_initialized = 0;
39a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walshstatic __thread char destructor_initialized;
408c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalley
4113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
4213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * setransd_open
4313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * This function opens a socket to the setransd.
4513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Returns:  on success, a file descriptor ( >= 0 ) to the socket
4613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *           on error, a negative value
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int setransd_open(void)
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
5013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct sockaddr_un addr;
5113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int fd;
5213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#ifdef SOCK_CLOEXEC
5313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fd = socket(PF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
5413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0 && errno == EINVAL)
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#endif
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	{
5713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		fd = socket(PF_UNIX, SOCK_STREAM, 0);
5813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (fd >= 0)
59aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris			if (fcntl(fd, F_SETFD, FD_CLOEXEC)) {
60aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris				close(fd);
61aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris				return -1;
62aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris			}
6313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
6413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
6513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
6613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
6713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(&addr, 0, sizeof(addr));
6813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	addr.sun_family = AF_UNIX;
6913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path));
7013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
7113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		close(fd);
7213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
7313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
7413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return fd;
7613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
7713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
7813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Returns: 0 on success, <0 on failure */
7913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int
8013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlesend_request(int fd, uint32_t function, const char *data1, const char *data2)
8113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
8213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct msghdr msgh;
8313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct iovec iov[5];
8413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t data1_size;
8513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t data2_size;
8613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t count, expected;
8713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	unsigned int i;
8813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
8913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
9013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
9113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!data1)
9313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		data1 = "";
9413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!data2)
9513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		data2 = "";
9613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
9713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data1_size = strlen(data1) + 1;
9813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data2_size = strlen(data2) + 1;
9913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
10013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[0].iov_base = &function;
10113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[0].iov_len = sizeof(function);
10213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[1].iov_base = &data1_size;
10313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[1].iov_len = sizeof(data1_size);
10413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[2].iov_base = &data2_size;
10513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[2].iov_len = sizeof(data2_size);
10613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[3].iov_base = (char *)data1;
10713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[3].iov_len = data1_size;
10813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[4].iov_base = (char *)data2;
10913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	iov[4].iov_len = data2_size;
11013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(&msgh, 0, sizeof(msgh));
11113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	msgh.msg_iov = iov;
11213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	msgh.msg_iovlen = sizeof(iov) / sizeof(iov[0]);
11313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	expected = 0;
11513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	for (i = 0; i < sizeof(iov) / sizeof(iov[0]); i++)
11613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		expected += iov[i].iov_len;
11713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
11813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (((count = sendmsg(fd, &msgh, MSG_NOSIGNAL)) < 0)
11913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	       && (errno == EINTR)) ;
12013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (count < 0 || count != expected)
12113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
12213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
12413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
12513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
12613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/* Returns: 0 on success, <0 on failure */
12713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic int
12813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlereceive_response(int fd, uint32_t function, char **outdata, int32_t * ret_val)
12913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
13013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct iovec resp_hdr[3];
13113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t func;
13213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	uint32_t data_size;
13313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	char *data;
13413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct iovec resp_data;
13513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ssize_t count;
13613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
13713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
13813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
13913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[0].iov_base = &func;
14113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[0].iov_len = sizeof(func);
14213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[1].iov_base = &data_size;
14313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[1].iov_len = sizeof(data_size);
14413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[2].iov_base = ret_val;
14513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_hdr[2].iov_len = sizeof(*ret_val);
14613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
14713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (((count = readv(fd, resp_hdr, 3)) < 0) && (errno == EINTR)) ;
14813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (count != (sizeof(func) + sizeof(data_size) + sizeof(*ret_val))) {
14913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
15013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (func != function || !data_size || data_size > MAX_DATA_BUF) {
15313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
15413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
15513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
15613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	data = malloc(data_size);
157aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris	if (!data)
15813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
159aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris	/* coveriety doesn't realize that data will be initialized in readv */
160aa62cd60f7192123b509c2518e7a2083e34a65a2Eric Paris	memset(data, 0, data_size);
16113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_data.iov_base = data;
16313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	resp_data.iov_len = data_size;
16413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
16513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (((count = readv(fd, &resp_data, 1))) < 0 && (errno == EINTR)) ;
16613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (count < 0 || (uint32_t) count != data_size ||
16713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	    data[data_size - 1] != '\0') {
16813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		free(data);
16913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
17013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
17113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*outdata = data;
17213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
17313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
17413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1756a17cfaafcdab82c9909eccff56968913b36a631KaiGai Koheistatic int raw_to_trans_context(const char *raw, char **transp)
17613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
17713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
17813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int32_t ret_val;
17913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int fd;
18013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*transp = NULL;
18213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fd = setransd_open();
18413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
18513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return fd;
18613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
18713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = send_request(fd, RAW_TO_TRANS_CONTEXT, raw, NULL);
18813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
18913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
19013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = receive_response(fd, RAW_TO_TRANS_CONTEXT, transp, &ret_val);
19213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
19313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
19413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
19513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = ret_val;
19613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
19713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	close(fd);
19813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
19913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
20013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2016a17cfaafcdab82c9909eccff56968913b36a631KaiGai Koheistatic int trans_to_raw_context(const char *trans, char **rawp)
20213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
20313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int ret;
20413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int32_t ret_val;
20513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int fd;
20613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*rawp = NULL;
20813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
20913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	fd = setransd_open();
21013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (fd < 0)
21113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return fd;
21213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = send_request(fd, TRANS_TO_RAW_CONTEXT, trans, NULL);
21313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
21413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = receive_response(fd, TRANS_TO_RAW_CONTEXT, rawp, &ret_val);
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (ret)
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
21913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	ret = ret_val;
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	close(fd);
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return ret;
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2266a17cfaafcdab82c9909eccff56968913b36a631KaiGai Koheistatic int raw_context_to_color(const char *raw, char **colors)
227cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh{
228cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	int ret;
229cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	int32_t ret_val;
230cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	int fd;
231cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
232cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	fd = setransd_open();
233cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	if (fd < 0)
234cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		return fd;
235cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
236cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	ret = send_request(fd, RAW_CONTEXT_TO_COLOR, raw, NULL);
237cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	if (ret)
238cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		goto out;
239cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
240cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	ret = receive_response(fd, RAW_CONTEXT_TO_COLOR, colors, &ret_val);
241cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	if (ret)
242cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		goto out;
243cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
244cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	ret = ret_val;
245cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walshout:
246cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	close(fd);
247cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	return ret;
248cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh}
249cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
250a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walshstatic void setrans_thread_destructor(void __attribute__((unused)) *unused)
251a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh{
252a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_t2r_trans);
253a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_t2r_raw);
254a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_r2t_trans);
255a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_r2t_raw);
256a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_r2c_trans);
257a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	free(prev_r2c_raw);
258a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh}
259a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh
260da5e7e3b81c8300f597d01907d1b228e51ebe8f9Daniel P. Berrangevoid __attribute__((destructor)) setrans_lib_destructor(void);
261da5e7e3b81c8300f597d01907d1b228e51ebe8f9Daniel P. Berrange
262a4f84109b51263599a284b167bf04e088e7da95dLaurent Bigonvillevoid hidden __attribute__((destructor)) setrans_lib_destructor(void)
263f0b3127ca3c99ae218dba43a6e3f7430081c412bEamon Walsh{
264a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans)
265a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley		return;
2661629d2f89a8c5f758413b87b94740aaaa5f21144Daniel J Walsh	if (destructor_key_initialized)
2671629d2f89a8c5f758413b87b94740aaaa5f21144Daniel J Walsh		__selinux_key_delete(destructor_key);
268f0b3127ca3c99ae218dba43a6e3f7430081c412bEamon Walsh}
269f0b3127ca3c99ae218dba43a6e3f7430081c412bEamon Walsh
270a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walshstatic inline void init_thread_destructor(void)
271a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh{
272a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans)
273a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley		return;
274a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	if (destructor_initialized == 0) {
275a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh		__selinux_setspecific(destructor_key, (void *)1);
276a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh		destructor_initialized = 1;
277a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	}
278a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh}
279a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh
2808c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalleystatic void init_context_translations(void)
28113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
282a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	has_setrans = (access(SETRANS_UNIX_SOCKET, F_OK) == 0);
283a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans)
284a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley		return;
2851629d2f89a8c5f758413b87b94740aaaa5f21144Daniel J Walsh	if (__selinux_key_create(&destructor_key, setrans_thread_destructor) == 0)
2861629d2f89a8c5f758413b87b94740aaaa5f21144Daniel J Walsh		destructor_key_initialized = 1;
28713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
28813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2899eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_trans_to_raw_context(const char * trans,
2909eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley				 char ** rawp)
29113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
29213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!trans) {
29313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*rawp = NULL;
29413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
29513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
29613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2978c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalley	__selinux_once(once, init_context_translations);
298a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	init_thread_destructor();
2998c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalley
300a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans) {
30113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*rawp = strdup(trans);
30213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
30313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
30413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3051ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	if (prev_t2r_trans && strcmp(prev_t2r_trans, trans) == 0) {
3061ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		*rawp = strdup(prev_t2r_raw);
3071ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	} else {
3081ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_t2r_trans);
3091ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_t2r_trans = NULL;
3101ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_t2r_raw);
3111ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_t2r_raw = NULL;
31213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (trans_to_raw_context(trans, rawp))
31313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*rawp = strdup(trans);
31413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*rawp) {
3151ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_t2r_trans = strdup(trans);
3161ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_t2r_trans)
3171ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				goto out;
3181ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_t2r_raw = strdup(*rawp);
3191ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_t2r_raw) {
3201ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				free(prev_t2r_trans);
3211ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				prev_t2r_trans = NULL;
3221ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			}
32313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
32413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
32513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
32613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *rawp ? 0 : -1;
32713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
32813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
32913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_trans_to_raw_context)
33013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3319eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_raw_to_trans_context(const char * raw,
3329eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley				 char ** transp)
33313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
33413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!raw) {
33513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*transp = NULL;
33613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
33713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
33813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3398c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalley	__selinux_once(once, init_context_translations);
340a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	init_thread_destructor();
3418c372f665db44cf753bb299e2ee7dcf6143b9e9eStephen Smalley
342a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans)  {
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*transp = strdup(raw);
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
3471ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	if (prev_r2t_raw && strcmp(prev_r2t_raw, raw) == 0) {
3481ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		*transp = strdup(prev_r2t_trans);
3491ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	} else {
3501ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_r2t_raw);
3511ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_r2t_raw = NULL;
3521ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_r2t_trans);
3531ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_r2t_trans = NULL;
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (raw_to_trans_context(raw, transp))
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			*transp = strdup(raw);
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (*transp) {
3571ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_r2t_raw = strdup(raw);
3581ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_r2t_raw)
3591ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				goto out;
3601ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_r2t_trans = strdup(*transp);
3611ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_r2t_trans) {
3621ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				free(prev_r2t_raw);
3631ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				prev_r2t_raw = NULL;
3641ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			}
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		}
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle      out:
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *transp ? 0 : -1;
36913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
37013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_raw_to_trans_context)
372cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
3739eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_raw_context_to_color(const char * raw, char **transp)
374cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh{
375cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	if (!raw) {
376cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		*transp = NULL;
377cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		return -1;
378cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	}
379cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
380a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	__selinux_once(once, init_context_translations);
381a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh	init_thread_destructor();
382a29ff33baf366825c0fbe721d30b12b5b96a64e1Eamon Walsh
383a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	if (!has_setrans) {
384a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley		*transp = strdup(raw);
385a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley		goto out;
386a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley	}
387a03f006d7e02a394dcaa55fc4fab6d3d46890224Stephen Smalley
3881ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	if (prev_r2c_raw && strcmp(prev_r2c_raw, raw) == 0) {
3891ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		*transp = strdup(prev_r2c_trans);
3901ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley	} else {
3911ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_r2c_raw);
3921ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_r2c_raw = NULL;
3931ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		free(prev_r2c_trans);
3941ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley		prev_r2c_trans = NULL;
395cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		if (raw_context_to_color(raw, transp))
396cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh			return -1;
397cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		if (*transp) {
3981ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_r2c_raw = strdup(raw);
3991ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_r2c_raw)
4001ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				goto out;
4011ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			prev_r2c_trans = strdup(*transp);
4021ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			if (!prev_r2c_trans) {
4031ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				free(prev_r2c_raw);
4041ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley				prev_r2c_raw = NULL;
4051ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley			}
406cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh		}
407cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	}
4081ac1ff6382505fa1e245fdc9c91b2448a7843101Stephen Smalley      out:
409cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh	return *transp ? 0 : -1;
410cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh}
411cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walsh
412cfa3cb6fa5d0cc00fde75ee74ec2da577f62e141Eamon Walshhidden_def(selinux_raw_context_to_color)
41313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#else /*DISABLE_SETRANS*/
41413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4159eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_trans_to_raw_context(const char * trans,
4169eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley				 char ** rawp)
41713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
41813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!trans) {
41913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*rawp = NULL;
42013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
42113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
42213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*rawp = strdup(trans);
42413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *rawp ? 0 : -1;
42613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
42713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_trans_to_raw_context)
42913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4309eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalleyint selinux_raw_to_trans_context(const char * raw,
4319eb9c9327563014ad6a807814e7975424642d5b9Stephen Smalley				 char ** transp)
43213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
43313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!raw) {
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		*transp = NULL;
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return 0;
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
43713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*transp = strdup(raw);
43813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
43913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *transp ? 0 : -1;
44013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
44113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlehidden_def(selinux_raw_to_trans_context)
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#endif /*DISABLE_SETRANS*/
444