16cd6a6acSopenharmony_ci#include <unistd.h> 26cd6a6acSopenharmony_ci#include <sys/types.h> 36cd6a6acSopenharmony_ci#include <fcntl.h> 46cd6a6acSopenharmony_ci#include <stdlib.h> 56cd6a6acSopenharmony_ci#include <stdio.h> 66cd6a6acSopenharmony_ci#include <errno.h> 76cd6a6acSopenharmony_ci#include <string.h> 86cd6a6acSopenharmony_ci#include <limits.h> 96cd6a6acSopenharmony_ci#include <ctype.h> 106cd6a6acSopenharmony_ci#include "selinux_internal.h" 116cd6a6acSopenharmony_ci#include "policy.h" 126cd6a6acSopenharmony_ci#include "mapping.h" 136cd6a6acSopenharmony_ci 146cd6a6acSopenharmony_cistatic int object_name_encode(const char *objname, char *buffer, size_t buflen) 156cd6a6acSopenharmony_ci{ 166cd6a6acSopenharmony_ci int code; 176cd6a6acSopenharmony_ci size_t offset = 0; 186cd6a6acSopenharmony_ci 196cd6a6acSopenharmony_ci if (buflen - offset < 1) 206cd6a6acSopenharmony_ci return -1; 216cd6a6acSopenharmony_ci buffer[offset++] = ' '; 226cd6a6acSopenharmony_ci 236cd6a6acSopenharmony_ci do { 246cd6a6acSopenharmony_ci code = *objname++; 256cd6a6acSopenharmony_ci 266cd6a6acSopenharmony_ci if (isalnum(code) || code == '\0' || code == '-' || 276cd6a6acSopenharmony_ci code == '.' || code == '_' || code == '~') { 286cd6a6acSopenharmony_ci if (buflen - offset < 1) 296cd6a6acSopenharmony_ci return -1; 306cd6a6acSopenharmony_ci buffer[offset++] = code; 316cd6a6acSopenharmony_ci } else if (code == ' ') { 326cd6a6acSopenharmony_ci if (buflen - offset < 1) 336cd6a6acSopenharmony_ci return -1; 346cd6a6acSopenharmony_ci buffer[offset++] = '+'; 356cd6a6acSopenharmony_ci } else { 366cd6a6acSopenharmony_ci static const char *table = "0123456789ABCDEF"; 376cd6a6acSopenharmony_ci int l = (code & 0x0f); 386cd6a6acSopenharmony_ci int h = (code & 0xf0) >> 4; 396cd6a6acSopenharmony_ci 406cd6a6acSopenharmony_ci if (buflen - offset < 3) 416cd6a6acSopenharmony_ci return -1; 426cd6a6acSopenharmony_ci buffer[offset++] = '%'; 436cd6a6acSopenharmony_ci buffer[offset++] = table[h]; 446cd6a6acSopenharmony_ci buffer[offset++] = table[l]; 456cd6a6acSopenharmony_ci } 466cd6a6acSopenharmony_ci } while (code != '\0'); 476cd6a6acSopenharmony_ci 486cd6a6acSopenharmony_ci return 0; 496cd6a6acSopenharmony_ci} 506cd6a6acSopenharmony_ci 516cd6a6acSopenharmony_ciint security_compute_create_name_raw(const char * scon, 526cd6a6acSopenharmony_ci const char * tcon, 536cd6a6acSopenharmony_ci security_class_t tclass, 546cd6a6acSopenharmony_ci const char *objname, 556cd6a6acSopenharmony_ci char ** newcon) 566cd6a6acSopenharmony_ci{ 576cd6a6acSopenharmony_ci char path[PATH_MAX]; 586cd6a6acSopenharmony_ci char *buf; 596cd6a6acSopenharmony_ci size_t size; 606cd6a6acSopenharmony_ci int fd, ret, len; 616cd6a6acSopenharmony_ci 626cd6a6acSopenharmony_ci if (!selinux_mnt) { 636cd6a6acSopenharmony_ci errno = ENOENT; 646cd6a6acSopenharmony_ci return -1; 656cd6a6acSopenharmony_ci } 666cd6a6acSopenharmony_ci 676cd6a6acSopenharmony_ci snprintf(path, sizeof path, "%s/create", selinux_mnt); 686cd6a6acSopenharmony_ci fd = open(path, O_RDWR | O_CLOEXEC); 696cd6a6acSopenharmony_ci if (fd < 0) 706cd6a6acSopenharmony_ci return -1; 716cd6a6acSopenharmony_ci 726cd6a6acSopenharmony_ci size = selinux_page_size; 736cd6a6acSopenharmony_ci buf = malloc(size); 746cd6a6acSopenharmony_ci if (!buf) { 756cd6a6acSopenharmony_ci ret = -1; 766cd6a6acSopenharmony_ci goto out; 776cd6a6acSopenharmony_ci } 786cd6a6acSopenharmony_ci 796cd6a6acSopenharmony_ci len = snprintf(buf, size, "%s %s %hu", 806cd6a6acSopenharmony_ci scon, tcon, unmap_class(tclass)); 816cd6a6acSopenharmony_ci if (len < 0 || (size_t)len >= size) { 826cd6a6acSopenharmony_ci errno = EOVERFLOW; 836cd6a6acSopenharmony_ci ret = -1; 846cd6a6acSopenharmony_ci goto out2; 856cd6a6acSopenharmony_ci } 866cd6a6acSopenharmony_ci 876cd6a6acSopenharmony_ci if (objname && 886cd6a6acSopenharmony_ci object_name_encode(objname, buf + len, size - len) < 0) { 896cd6a6acSopenharmony_ci errno = ENAMETOOLONG; 906cd6a6acSopenharmony_ci ret = -1; 916cd6a6acSopenharmony_ci goto out2; 926cd6a6acSopenharmony_ci } 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci ret = write(fd, buf, strlen(buf)); 956cd6a6acSopenharmony_ci if (ret < 0) 966cd6a6acSopenharmony_ci goto out2; 976cd6a6acSopenharmony_ci 986cd6a6acSopenharmony_ci memset(buf, 0, size); 996cd6a6acSopenharmony_ci ret = read(fd, buf, size - 1); 1006cd6a6acSopenharmony_ci if (ret < 0) 1016cd6a6acSopenharmony_ci goto out2; 1026cd6a6acSopenharmony_ci 1036cd6a6acSopenharmony_ci *newcon = strdup(buf); 1046cd6a6acSopenharmony_ci if (!(*newcon)) { 1056cd6a6acSopenharmony_ci ret = -1; 1066cd6a6acSopenharmony_ci goto out2; 1076cd6a6acSopenharmony_ci } 1086cd6a6acSopenharmony_ci ret = 0; 1096cd6a6acSopenharmony_ci out2: 1106cd6a6acSopenharmony_ci free(buf); 1116cd6a6acSopenharmony_ci out: 1126cd6a6acSopenharmony_ci close(fd); 1136cd6a6acSopenharmony_ci return ret; 1146cd6a6acSopenharmony_ci} 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ciint security_compute_create_raw(const char * scon, 1176cd6a6acSopenharmony_ci const char * tcon, 1186cd6a6acSopenharmony_ci security_class_t tclass, 1196cd6a6acSopenharmony_ci char ** newcon) 1206cd6a6acSopenharmony_ci{ 1216cd6a6acSopenharmony_ci return security_compute_create_name_raw(scon, tcon, tclass, 1226cd6a6acSopenharmony_ci NULL, newcon); 1236cd6a6acSopenharmony_ci} 1246cd6a6acSopenharmony_ci 1256cd6a6acSopenharmony_ciint security_compute_create_name(const char * scon, 1266cd6a6acSopenharmony_ci const char * tcon, 1276cd6a6acSopenharmony_ci security_class_t tclass, 1286cd6a6acSopenharmony_ci const char *objname, 1296cd6a6acSopenharmony_ci char ** newcon) 1306cd6a6acSopenharmony_ci{ 1316cd6a6acSopenharmony_ci int ret; 1326cd6a6acSopenharmony_ci char * rscon; 1336cd6a6acSopenharmony_ci char * rtcon; 1346cd6a6acSopenharmony_ci char * rnewcon; 1356cd6a6acSopenharmony_ci 1366cd6a6acSopenharmony_ci if (selinux_trans_to_raw_context(scon, &rscon)) 1376cd6a6acSopenharmony_ci return -1; 1386cd6a6acSopenharmony_ci if (selinux_trans_to_raw_context(tcon, &rtcon)) { 1396cd6a6acSopenharmony_ci freecon(rscon); 1406cd6a6acSopenharmony_ci return -1; 1416cd6a6acSopenharmony_ci } 1426cd6a6acSopenharmony_ci 1436cd6a6acSopenharmony_ci ret = security_compute_create_name_raw(rscon, rtcon, tclass, 1446cd6a6acSopenharmony_ci objname, &rnewcon); 1456cd6a6acSopenharmony_ci freecon(rscon); 1466cd6a6acSopenharmony_ci freecon(rtcon); 1476cd6a6acSopenharmony_ci if (!ret) { 1486cd6a6acSopenharmony_ci ret = selinux_raw_to_trans_context(rnewcon, newcon); 1496cd6a6acSopenharmony_ci freecon(rnewcon); 1506cd6a6acSopenharmony_ci } 1516cd6a6acSopenharmony_ci 1526cd6a6acSopenharmony_ci return ret; 1536cd6a6acSopenharmony_ci} 1546cd6a6acSopenharmony_ci 1556cd6a6acSopenharmony_ciint security_compute_create(const char * scon, 1566cd6a6acSopenharmony_ci const char * tcon, 1576cd6a6acSopenharmony_ci security_class_t tclass, 1586cd6a6acSopenharmony_ci char ** newcon) 1596cd6a6acSopenharmony_ci{ 1606cd6a6acSopenharmony_ci return security_compute_create_name(scon, tcon, tclass, NULL, newcon); 1616cd6a6acSopenharmony_ci} 162