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