1/* 2 * Class and permission mappings. 3 */ 4 5#include <errno.h> 6#include <stdio.h> 7#include <stdlib.h> 8#include <stdarg.h> 9#include <stdbool.h> 10#include <selinux/selinux.h> 11#include <selinux/avc.h> 12#include "callbacks.h" 13#include "mapping.h" 14#include "selinux_internal.h" 15 16/* 17 * Class and permission mappings 18 */ 19 20struct selinux_mapping { 21 security_class_t value; /* real, kernel value */ 22 unsigned num_perms; 23 access_vector_t perms[sizeof(access_vector_t) * 8]; 24}; 25 26static struct selinux_mapping *current_mapping = NULL; 27static security_class_t current_mapping_size = 0; 28 29/* 30 * Mapping setting function 31 */ 32 33int 34selinux_set_mapping(struct security_class_mapping *map) 35{ 36 size_t size = sizeof(struct selinux_mapping); 37 security_class_t i, j; 38 unsigned k; 39 bool print_unknown_handle = false; 40 bool reject = (security_reject_unknown() == 1); 41 bool deny = (security_deny_unknown() == 1); 42 43 free(current_mapping); 44 current_mapping = NULL; 45 current_mapping_size = 0; 46 47 if (avc_reset() < 0) 48 goto err; 49 50 /* Find number of classes in the input mapping */ 51 if (!map) { 52 errno = EINVAL; 53 goto err; 54 } 55 i = 0; 56 while (map[i].name) 57 i++; 58 59 /* Allocate space for the class records, plus one for class zero */ 60 current_mapping = (struct selinux_mapping *)calloc(++i, size); 61 if (!current_mapping) 62 goto err; 63 64 /* Store the raw class and permission values */ 65 j = 0; 66 while (map[j].name) { 67 struct security_class_mapping *p_in = map + (j++); 68 struct selinux_mapping *p_out = current_mapping + j; 69 70 p_out->value = string_to_security_class(p_in->name); 71 if (!p_out->value) { 72 selinux_log(SELINUX_INFO, 73 "SELinux: Class %s not defined in policy.\n", 74 p_in->name); 75 if (reject) 76 goto err2; 77 p_out->num_perms = 0; 78 print_unknown_handle = true; 79 continue; 80 } 81 82 k = 0; 83 while (p_in->perms[k]) { 84 /* An empty permission string skips ahead */ 85 if (!*p_in->perms[k]) { 86 k++; 87 continue; 88 } 89 p_out->perms[k] = string_to_av_perm(p_out->value, 90 p_in->perms[k]); 91 if (!p_out->perms[k]) { 92 selinux_log(SELINUX_INFO, 93 "SELinux: Permission %s in class %s not defined in policy.\n", 94 p_in->perms[k], p_in->name); 95 if (reject) 96 goto err2; 97 print_unknown_handle = true; 98 } 99 k++; 100 } 101 p_out->num_perms = k; 102 } 103 104 if (print_unknown_handle) 105 selinux_log(SELINUX_INFO, 106 "SELinux: the above unknown classes and permissions will be %s\n", 107 deny ? "denied" : "allowed"); 108 109 /* Set the mapping size here so the above lookups are "raw" */ 110 current_mapping_size = i; 111 return 0; 112err2: 113 free(current_mapping); 114 current_mapping = NULL; 115 current_mapping_size = 0; 116err: 117 return -1; 118} 119 120/* 121 * Get real, kernel values from mapped values 122 */ 123 124security_class_t 125unmap_class(security_class_t tclass) 126{ 127 if (tclass < current_mapping_size) 128 return current_mapping[tclass].value; 129 130 /* If here no mapping set or the class requested is not valid. */ 131 if (current_mapping_size != 0) { 132 errno = EINVAL; 133 return 0; 134 } 135 else 136 return tclass; 137} 138 139access_vector_t 140unmap_perm(security_class_t tclass, access_vector_t tperm) 141{ 142 if (tclass < current_mapping_size) { 143 unsigned i; 144 access_vector_t kperm = 0; 145 146 for (i = 0; i < current_mapping[tclass].num_perms; i++) 147 if (tperm & (UINT32_C(1)<<i)) { 148 kperm |= current_mapping[tclass].perms[i]; 149 tperm &= ~(UINT32_C(1)<<i); 150 } 151 return kperm; 152 } 153 154 /* If here no mapping set or the perm requested is not valid. */ 155 if (current_mapping_size != 0) { 156 errno = EINVAL; 157 return 0; 158 } 159 else 160 return tperm; 161} 162 163/* 164 * Get mapped values from real, kernel values 165 */ 166 167security_class_t 168map_class(security_class_t kclass) 169{ 170 security_class_t i; 171 172 for (i = 0; i < current_mapping_size; i++) 173 if (current_mapping[i].value == kclass) 174 return i; 175 176/* If here no mapping set or the class requested is not valid. */ 177 if (current_mapping_size != 0) { 178 errno = EINVAL; 179 return 0; 180 } 181 else 182 return kclass; 183} 184 185access_vector_t 186map_perm(security_class_t tclass, access_vector_t kperm) 187{ 188 if (tclass < current_mapping_size) { 189 unsigned i; 190 access_vector_t tperm = 0; 191 192 for (i = 0; i < current_mapping[tclass].num_perms; i++) 193 if (kperm & current_mapping[tclass].perms[i]) { 194 tperm |= UINT32_C(1)<<i; 195 kperm &= ~current_mapping[tclass].perms[i]; 196 } 197 198 if (tperm == 0) { 199 errno = EINVAL; 200 return 0; 201 } 202 else 203 return tperm; 204 } 205 return kperm; 206} 207 208void 209map_decision(security_class_t tclass, struct av_decision *avd) 210{ 211 if (tclass < current_mapping_size) { 212 bool allow_unknown = (security_deny_unknown() == 0); 213 struct selinux_mapping *mapping = ¤t_mapping[tclass]; 214 unsigned int i, n = mapping->num_perms; 215 access_vector_t result; 216 217 for (i = 0, result = 0; i < n; i++) { 218 if (avd->allowed & mapping->perms[i]) 219 result |= UINT32_C(1)<<i; 220 else if (allow_unknown && !mapping->perms[i]) 221 result |= UINT32_C(1)<<i; 222 } 223 avd->allowed = result; 224 225 for (i = 0, result = 0; i < n; i++) { 226 if (avd->decided & mapping->perms[i]) 227 result |= UINT32_C(1)<<i; 228 else if (allow_unknown && !mapping->perms[i]) 229 result |= UINT32_C(1)<<i; 230 } 231 avd->decided = result; 232 233 for (i = 0, result = 0; i < n; i++) 234 if (avd->auditallow & mapping->perms[i]) 235 result |= UINT32_C(1)<<i; 236 avd->auditallow = result; 237 238 for (i = 0, result = 0; i < n; i++) { 239 if (avd->auditdeny & mapping->perms[i]) 240 result |= UINT32_C(1)<<i; 241 else if (!allow_unknown && !mapping->perms[i]) 242 result |= UINT32_C(1)<<i; 243 } 244 245 /* 246 * Make sure we audit denials for any permission check 247 * beyond the mapping->num_perms since this indicates 248 * a bug in the object manager. 249 */ 250 for (; i < (sizeof(result)*8); i++) 251 result |= UINT32_C(1)<<i; 252 avd->auditdeny = result; 253 } 254} 255