1#include <unistd.h> 2#include <sys/types.h> 3#include <fcntl.h> 4#include <stdlib.h> 5#include <stdio.h> 6#include <errno.h> 7#include <string.h> 8#include <limits.h> 9#include <ctype.h> 10#include "selinux_internal.h" 11#include "policy.h" 12#include "mapping.h" 13 14static int object_name_encode(const char *objname, char *buffer, size_t buflen) 15{ 16 int code; 17 size_t offset = 0; 18 19 if (buflen - offset < 1) 20 return -1; 21 buffer[offset++] = ' '; 22 23 do { 24 code = *objname++; 25 26 if (isalnum(code) || code == '\0' || code == '-' || 27 code == '.' || code == '_' || code == '~') { 28 if (buflen - offset < 1) 29 return -1; 30 buffer[offset++] = code; 31 } else if (code == ' ') { 32 if (buflen - offset < 1) 33 return -1; 34 buffer[offset++] = '+'; 35 } else { 36 static const char *table = "0123456789ABCDEF"; 37 int l = (code & 0x0f); 38 int h = (code & 0xf0) >> 4; 39 40 if (buflen - offset < 3) 41 return -1; 42 buffer[offset++] = '%'; 43 buffer[offset++] = table[h]; 44 buffer[offset++] = table[l]; 45 } 46 } while (code != '\0'); 47 48 return 0; 49} 50 51int security_compute_create_name_raw(const char * scon, 52 const char * tcon, 53 security_class_t tclass, 54 const char *objname, 55 char ** newcon) 56{ 57 char path[PATH_MAX]; 58 char *buf; 59 size_t size; 60 int fd, ret, len; 61 62 if (!selinux_mnt) { 63 errno = ENOENT; 64 return -1; 65 } 66 67 snprintf(path, sizeof path, "%s/create", selinux_mnt); 68 fd = open(path, O_RDWR | O_CLOEXEC); 69 if (fd < 0) 70 return -1; 71 72 size = selinux_page_size; 73 buf = malloc(size); 74 if (!buf) { 75 ret = -1; 76 goto out; 77 } 78 79 len = snprintf(buf, size, "%s %s %hu", 80 scon, tcon, unmap_class(tclass)); 81 if (len < 0 || (size_t)len >= size) { 82 errno = EOVERFLOW; 83 ret = -1; 84 goto out2; 85 } 86 87 if (objname && 88 object_name_encode(objname, buf + len, size - len) < 0) { 89 errno = ENAMETOOLONG; 90 ret = -1; 91 goto out2; 92 } 93 94 ret = write(fd, buf, strlen(buf)); 95 if (ret < 0) 96 goto out2; 97 98 memset(buf, 0, size); 99 ret = read(fd, buf, size - 1); 100 if (ret < 0) 101 goto out2; 102 103 *newcon = strdup(buf); 104 if (!(*newcon)) { 105 ret = -1; 106 goto out2; 107 } 108 ret = 0; 109 out2: 110 free(buf); 111 out: 112 close(fd); 113 return ret; 114} 115 116int security_compute_create_raw(const char * scon, 117 const char * tcon, 118 security_class_t tclass, 119 char ** newcon) 120{ 121 return security_compute_create_name_raw(scon, tcon, tclass, 122 NULL, newcon); 123} 124 125int security_compute_create_name(const char * scon, 126 const char * tcon, 127 security_class_t tclass, 128 const char *objname, 129 char ** newcon) 130{ 131 int ret; 132 char * rscon; 133 char * rtcon; 134 char * rnewcon; 135 136 if (selinux_trans_to_raw_context(scon, &rscon)) 137 return -1; 138 if (selinux_trans_to_raw_context(tcon, &rtcon)) { 139 freecon(rscon); 140 return -1; 141 } 142 143 ret = security_compute_create_name_raw(rscon, rtcon, tclass, 144 objname, &rnewcon); 145 freecon(rscon); 146 freecon(rtcon); 147 if (!ret) { 148 ret = selinux_raw_to_trans_context(rnewcon, newcon); 149 freecon(rnewcon); 150 } 151 152 return ret; 153} 154 155int security_compute_create(const char * scon, 156 const char * tcon, 157 security_class_t tclass, 158 char ** newcon) 159{ 160 return security_compute_create_name(scon, tcon, tclass, NULL, newcon); 161} 162