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