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