1 #include <stdio.h> 2 #include <stdio_ext.h> 3 #include <string.h> 4 #include <ctype.h> 5 #include <stddef.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <limits.h> 9 #include <unistd.h> 10 #include <pthread.h> 11 #include <errno.h> 12 #include "policy.h" 13 #include "selinux_internal.h" 14 #include "get_default_type_internal.h" 15 16 #define SELINUXDIR "/etc/selinux/" 17 #define SELINUXCONFIG SELINUXDIR "config" 18 #define SELINUXDEFAULT "targeted" 19 #define SELINUXTYPETAG "SELINUXTYPE=" 20 #define SELINUXTAG "SELINUX=" 21 #define SETLOCALDEFS "SETLOCALDEFS=" 22 #define REQUIRESEUSERS "REQUIRESEUSERS=" 23 24 /* Indices for file paths arrays. */ 25 #define BINPOLICY 0 26 #define CONTEXTS_DIR 1 27 #define FILE_CONTEXTS 2 28 #define HOMEDIR_CONTEXTS 3 29 #define DEFAULT_CONTEXTS 4 30 #define USER_CONTEXTS 5 31 #define FAILSAFE_CONTEXT 6 32 #define DEFAULT_TYPE 7 33 #define BOOLEANS 8 34 #define MEDIA_CONTEXTS 9 35 #define REMOVABLE_CONTEXT 10 36 #define CUSTOMIZABLE_TYPES 11 37 #define USERS_DIR 12 38 #define SEUSERS 13 39 #define TRANSLATIONS 14 40 #define NETFILTER_CONTEXTS 15 41 #define FILE_CONTEXTS_HOMEDIR 16 42 #define FILE_CONTEXTS_LOCAL 17 43 #define SECURETTY_TYPES 18 44 #define X_CONTEXTS 19 45 #define COLORS 20 46 #define VIRTUAL_DOMAIN 21 47 #define VIRTUAL_IMAGE 22 48 #define FILE_CONTEXT_SUBS 23 49 #define SEPGSQL_CONTEXTS 24 50 #define FILE_CONTEXT_SUBS_DIST 25 51 #define LXC_CONTEXTS 26 52 #define BOOLEAN_SUBS 27 53 #define SYSTEMD_CONTEXTS 28 54 #define NEL 29 55 56 /* Part of one-time lazy init */ 57 static pthread_once_t once = PTHREAD_ONCE_INIT; 58 static void init_selinux_config(void); 59 60 /* New layout is relative to SELINUXDIR/policytype. */ 61 static char *file_paths[NEL]; 62 #define L1(l) L2(l) 63 #define L2(l)str##l 64 static const union file_path_suffixes_data { 65 struct { 66 #define S_(n, s) char L1(__LINE__)[sizeof(s)]; 67 #include "file_path_suffixes.h" 68 #undef S_ 69 }; 70 char str[0]; 71 } file_path_suffixes_data = { 72 { 73 #define S_(n, s) s, 74 #include "file_path_suffixes.h" 75 #undef S_ 76 } 77 }; 78 static const uint16_t file_path_suffixes_idx[NEL] = { 79 #define S_(n, s) [n] = offsetof(union file_path_suffixes_data, L1(__LINE__)), 80 #include "file_path_suffixes.h" 81 #undef S_ 82 }; 83 84 #undef L1 85 #undef L2 86 87 int selinux_getenforcemode(int *enforce) 88 { 89 int ret = -1; 90 FILE *cfg = fopen(SELINUXCONFIG, "r"); 91 if (cfg) { 92 char *buf; 93 int len = sizeof(SELINUXTAG) - 1; 94 buf = malloc(selinux_page_size); 95 if (!buf) { 96 fclose(cfg); 97 return -1; 98 } 99 while (fgets_unlocked(buf, selinux_page_size, cfg)) { 100 if (strncmp(buf, SELINUXTAG, len)) 101 continue; 102 if (!strncasecmp 103 (buf + len, "enforcing", sizeof("enforcing") - 1)) { 104 *enforce = 1; 105 ret = 0; 106 break; 107 } else 108 if (!strncasecmp 109 (buf + len, "permissive", 110 sizeof("permissive") - 1)) { 111 *enforce = 0; 112 ret = 0; 113 break; 114 } else 115 if (!strncasecmp 116 (buf + len, "disabled", 117 sizeof("disabled") - 1)) { 118 *enforce = -1; 119 ret = 0; 120 break; 121 } 122 } 123 fclose(cfg); 124 free(buf); 125 } 126 return ret; 127 } 128 129 hidden_def(selinux_getenforcemode) 130 131 static char *selinux_policytype; 132 133 int selinux_getpolicytype(char **type) 134 { 135 __selinux_once(once, init_selinux_config); 136 if (!selinux_policytype) 137 return -1; 138 *type = strdup(selinux_policytype); 139 return *type ? 0 : -1; 140 } 141 142 hidden_def(selinux_getpolicytype) 143 144 static int setpolicytype(const char *type) 145 { 146 free(selinux_policytype); 147 selinux_policytype = strdup(type); 148 return selinux_policytype ? 0 : -1; 149 } 150 151 static char *selinux_policyroot = NULL; 152 static const char *selinux_rootpath = SELINUXDIR; 153 154 static void init_selinux_config(void) 155 { 156 int i, *intptr; 157 size_t line_len; 158 ssize_t len; 159 char *line_buf = NULL, *buf_p, *value, *type = NULL, *end; 160 FILE *fp; 161 162 if (selinux_policyroot) 163 return; 164 165 fp = fopen(SELINUXCONFIG, "r"); 166 if (fp) { 167 __fsetlocking(fp, FSETLOCKING_BYCALLER); 168 while ((len = getline(&line_buf, &line_len, fp)) > 0) { 169 if (line_buf[len - 1] == '\n') 170 line_buf[len - 1] = 0; 171 buf_p = line_buf; 172 while (isspace(*buf_p)) 173 buf_p++; 174 if (*buf_p == '#' || *buf_p == 0) 175 continue; 176 177 if (!strncasecmp(buf_p, SELINUXTYPETAG, 178 sizeof(SELINUXTYPETAG) - 1)) { 179 selinux_policytype = type = 180 strdup(buf_p + sizeof(SELINUXTYPETAG) - 1); 181 if (!type) 182 return; 183 end = type + strlen(type) - 1; 184 while ((end > type) && 185 (isspace(*end) || iscntrl(*end))) { 186 *end = 0; 187 end--; 188 } 189 continue; 190 } else if (!strncmp(buf_p, SETLOCALDEFS, 191 sizeof(SETLOCALDEFS) - 1)) { 192 value = buf_p + sizeof(SETLOCALDEFS) - 1; 193 intptr = &load_setlocaldefs; 194 } else if (!strncmp(buf_p, REQUIRESEUSERS, 195 sizeof(REQUIRESEUSERS) - 1)) { 196 value = buf_p + sizeof(REQUIRESEUSERS) - 1; 197 intptr = &require_seusers; 198 } else { 199 continue; 200 } 201 202 if (isdigit(*value)) 203 *intptr = atoi(value); 204 else if (strncasecmp(value, "true", sizeof("true") - 1)) 205 *intptr = 1; 206 else if (strncasecmp 207 (value, "false", sizeof("false") - 1)) 208 *intptr = 0; 209 } 210 free(line_buf); 211 fclose(fp); 212 } 213 214 if (!type) { 215 selinux_policytype = type = strdup(SELINUXDEFAULT); 216 if (!type) 217 return; 218 } 219 220 if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, type) == -1) 221 return; 222 223 for (i = 0; i < NEL; i++) 224 if (asprintf(&file_paths[i], "%s%s", 225 selinux_policyroot, 226 file_path_suffixes_data.str + 227 file_path_suffixes_idx[i]) 228 == -1) 229 return; 230 } 231 232 static void fini_selinux_policyroot(void) __attribute__ ((destructor)); 233 234 static void fini_selinux_policyroot(void) 235 { 236 int i; 237 free(selinux_policyroot); 238 selinux_policyroot = NULL; 239 for (i = 0; i < NEL; i++) { 240 free(file_paths[i]); 241 file_paths[i] = NULL; 242 } 243 free(selinux_policytype); 244 selinux_policytype = NULL; 245 } 246 247 void selinux_reset_config(void) 248 { 249 fini_selinux_policyroot(); 250 init_selinux_config(); 251 } 252 253 hidden_def(selinux_reset_config) 254 255 static const char *get_path(int idx) 256 { 257 __selinux_once(once, init_selinux_config); 258 return file_paths[idx]; 259 } 260 261 const char *selinux_default_type_path(void) 262 { 263 return get_path(DEFAULT_TYPE); 264 } 265 266 hidden_def(selinux_default_type_path) 267 268 const char *selinux_policy_root(void) 269 { 270 __selinux_once(once, init_selinux_config); 271 return selinux_policyroot; 272 } 273 274 int selinux_set_policy_root(const char *path) 275 { 276 int i; 277 char *policy_type = strrchr(path, '/'); 278 if (!policy_type) { 279 errno = EINVAL; 280 return -1; 281 } 282 policy_type++; 283 284 fini_selinuxmnt(); 285 fini_selinux_policyroot(); 286 287 selinux_policyroot = strdup(path); 288 if (! selinux_policyroot) 289 return -1; 290 291 if (setpolicytype(policy_type) != 0) 292 return -1; 293 294 for (i = 0; i < NEL; i++) 295 if (asprintf(&file_paths[i], "%s%s", 296 selinux_policyroot, 297 file_path_suffixes_data.str + 298 file_path_suffixes_idx[i]) 299 == -1) 300 return -1; 301 302 return 0; 303 } 304 305 const char *selinux_path(void) 306 { 307 return selinux_rootpath; 308 } 309 310 hidden_def(selinux_path) 311 312 const char *selinux_default_context_path(void) 313 { 314 return get_path(DEFAULT_CONTEXTS); 315 } 316 317 hidden_def(selinux_default_context_path) 318 319 const char *selinux_securetty_types_path(void) 320 { 321 return get_path(SECURETTY_TYPES); 322 } 323 324 hidden_def(selinux_securetty_types_path) 325 326 const char *selinux_failsafe_context_path(void) 327 { 328 return get_path(FAILSAFE_CONTEXT); 329 } 330 331 hidden_def(selinux_failsafe_context_path) 332 333 const char *selinux_removable_context_path(void) 334 { 335 return get_path(REMOVABLE_CONTEXT); 336 } 337 338 hidden_def(selinux_removable_context_path) 339 340 const char *selinux_binary_policy_path(void) 341 { 342 return get_path(BINPOLICY); 343 } 344 345 hidden_def(selinux_binary_policy_path) 346 347 const char *selinux_current_policy_path(void) 348 { 349 int rc = 0; 350 int vers = 0; 351 static char policy_path[PATH_MAX]; 352 353 if (selinux_mnt) { 354 snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt); 355 if (access(policy_path, F_OK) == 0 ) { 356 return policy_path; 357 } 358 } 359 vers = security_policyvers(); 360 do { 361 /* Check prior versions to see if old policy is available */ 362 snprintf(policy_path, sizeof(policy_path), "%s.%d", 363 selinux_binary_policy_path(), vers); 364 } while ((rc = access(policy_path, F_OK)) && --vers > 0); 365 366 if (rc) return NULL; 367 return policy_path; 368 } 369 370 hidden_def(selinux_current_policy_path) 371 372 const char *selinux_file_context_path(void) 373 { 374 return get_path(FILE_CONTEXTS); 375 } 376 377 hidden_def(selinux_file_context_path) 378 379 const char *selinux_homedir_context_path(void) 380 { 381 return get_path(HOMEDIR_CONTEXTS); 382 } 383 384 hidden_def(selinux_homedir_context_path) 385 386 const char *selinux_media_context_path(void) 387 { 388 return get_path(MEDIA_CONTEXTS); 389 } 390 391 hidden_def(selinux_media_context_path) 392 393 const char *selinux_customizable_types_path(void) 394 { 395 return get_path(CUSTOMIZABLE_TYPES); 396 } 397 398 hidden_def(selinux_customizable_types_path) 399 400 const char *selinux_contexts_path(void) 401 { 402 return get_path(CONTEXTS_DIR); 403 } 404 405 const char *selinux_user_contexts_path(void) 406 { 407 return get_path(USER_CONTEXTS); 408 } 409 410 hidden_def(selinux_user_contexts_path) 411 412 const char *selinux_booleans_path(void) 413 { 414 return get_path(BOOLEANS); 415 } 416 417 hidden_def(selinux_booleans_path) 418 419 const char *selinux_users_path(void) 420 { 421 return get_path(USERS_DIR); 422 } 423 424 hidden_def(selinux_users_path) 425 426 const char *selinux_usersconf_path(void) 427 { 428 return get_path(SEUSERS); 429 } 430 431 hidden_def(selinux_usersconf_path) 432 433 const char *selinux_translations_path(void) 434 { 435 return get_path(TRANSLATIONS); 436 } 437 438 hidden_def(selinux_translations_path) 439 440 const char *selinux_colors_path(void) 441 { 442 return get_path(COLORS); 443 } 444 445 hidden_def(selinux_colors_path) 446 447 const char *selinux_netfilter_context_path(void) 448 { 449 return get_path(NETFILTER_CONTEXTS); 450 } 451 452 hidden_def(selinux_netfilter_context_path) 453 454 const char *selinux_file_context_homedir_path(void) 455 { 456 return get_path(FILE_CONTEXTS_HOMEDIR); 457 } 458 459 hidden_def(selinux_file_context_homedir_path) 460 461 const char *selinux_file_context_local_path(void) 462 { 463 return get_path(FILE_CONTEXTS_LOCAL); 464 } 465 466 hidden_def(selinux_file_context_local_path) 467 468 const char *selinux_x_context_path(void) 469 { 470 return get_path(X_CONTEXTS); 471 } 472 473 hidden_def(selinux_x_context_path) 474 475 const char *selinux_virtual_domain_context_path(void) 476 { 477 return get_path(VIRTUAL_DOMAIN); 478 } 479 480 hidden_def(selinux_virtual_domain_context_path) 481 482 const char *selinux_virtual_image_context_path(void) 483 { 484 return get_path(VIRTUAL_IMAGE); 485 } 486 487 hidden_def(selinux_virtual_image_context_path) 488 489 const char *selinux_lxc_contexts_path(void) 490 { 491 return get_path(LXC_CONTEXTS); 492 } 493 494 hidden_def(selinux_lxc_contexts_path) 495 496 const char *selinux_systemd_contexts_path(void) 497 { 498 return get_path(SYSTEMD_CONTEXTS); 499 } 500 501 hidden_def(selinux_systemd_contexts_path) 502 503 const char * selinux_booleans_subs_path(void) { 504 return get_path(BOOLEAN_SUBS); 505 } 506 507 hidden_def(selinux_booleans_subs_path) 508 509 const char * selinux_file_context_subs_path(void) { 510 return get_path(FILE_CONTEXT_SUBS); 511 } 512 513 hidden_def(selinux_file_context_subs_path) 514 515 const char * selinux_file_context_subs_dist_path(void) { 516 return get_path(FILE_CONTEXT_SUBS_DIST); 517 } 518 519 hidden_def(selinux_file_context_subs_dist_path) 520 521 const char *selinux_sepgsql_context_path(void) 522 { 523 return get_path(SEPGSQL_CONTEXTS); 524 } 525 526 hidden_def(selinux_sepgsql_context_path) 527