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