Home | History | Annotate | Download | only in src
      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 				selinux_policytype = type =
    181 				    strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
    182 				if (!type)
    183 					return;
    184 				end = type + strlen(type) - 1;
    185 				while ((end > type) &&
    186 				       (isspace(*end) || iscntrl(*end))) {
    187 					*end = 0;
    188 					end--;
    189 				}
    190 				continue;
    191 			} else if (!strncmp(buf_p, SETLOCALDEFS,
    192 					    sizeof(SETLOCALDEFS) - 1)) {
    193 				value = buf_p + sizeof(SETLOCALDEFS) - 1;
    194 				intptr = &load_setlocaldefs;
    195 			} else if (!strncmp(buf_p, REQUIRESEUSERS,
    196 					    sizeof(REQUIRESEUSERS) - 1)) {
    197 				value = buf_p + sizeof(REQUIRESEUSERS) - 1;
    198 				intptr = &require_seusers;
    199 			} else {
    200 				continue;
    201 			}
    202 
    203 			if (isdigit(*value))
    204 				*intptr = atoi(value);
    205 			else if (strncasecmp(value, "true", sizeof("true") - 1))
    206 				*intptr = 1;
    207 			else if (strncasecmp
    208 				 (value, "false", sizeof("false") - 1))
    209 				*intptr = 0;
    210 		}
    211 		free(line_buf);
    212 		fclose(fp);
    213 	}
    214 
    215 	if (!type) {
    216 		selinux_policytype = type = strdup(SELINUXDEFAULT);
    217 		if (!type)
    218 			return;
    219 	}
    220 
    221 	if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, type) == -1)
    222 		return;
    223 
    224 	for (i = 0; i < NEL; i++)
    225 		if (asprintf(&file_paths[i], "%s%s",
    226 			     selinux_policyroot,
    227 			     file_path_suffixes_data.str +
    228 			     file_path_suffixes_idx[i])
    229 		    == -1)
    230 			return;
    231 }
    232 
    233 static void fini_selinux_policyroot(void) __attribute__ ((destructor));
    234 
    235 static void fini_selinux_policyroot(void)
    236 {
    237 	int i;
    238 	free(selinux_policyroot);
    239 	selinux_policyroot = NULL;
    240 	for (i = 0; i < NEL; i++) {
    241 		free(file_paths[i]);
    242 		file_paths[i] = NULL;
    243 	}
    244 	free(selinux_policytype);
    245 	selinux_policytype = NULL;
    246 }
    247 
    248 void selinux_reset_config(void)
    249 {
    250 	fini_selinux_policyroot();
    251 	init_selinux_config();
    252 }
    253 
    254 hidden_def(selinux_reset_config)
    255 
    256 static const char *get_path(int idx)
    257 {
    258 	__selinux_once(once, init_selinux_config);
    259 	return file_paths[idx];
    260 }
    261 
    262 const char *selinux_default_type_path(void)
    263 {
    264 	return get_path(DEFAULT_TYPE);
    265 }
    266 
    267 hidden_def(selinux_default_type_path)
    268 
    269 const char *selinux_policy_root(void)
    270 {
    271 	__selinux_once(once, init_selinux_config);
    272 	return selinux_policyroot;
    273 }
    274 
    275 int selinux_set_policy_root(const char *path)
    276 {
    277 	int i;
    278 	char *policy_type = strrchr(path, '/');
    279 	if (!policy_type) {
    280 		errno = EINVAL;
    281 		return -1;
    282 	}
    283 	policy_type++;
    284 
    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_openrc_contexts_path(void)
    497 {
    498     return get_path(OPENRC_CONTEXTS);
    499 }
    500 
    501 hidden_def(selinux_openrc_contexts_path)
    502 
    503 const char *selinux_openssh_contexts_path(void)
    504 {
    505     return get_path(OPENSSH_CONTEXTS);
    506 }
    507 
    508 hidden_def(selinux_openssh_contexts_path)
    509 
    510 const char *selinux_snapperd_contexts_path(void)
    511 {
    512     return get_path(SNAPPERD_CONTEXTS);
    513 }
    514 
    515 hidden_def(selinux_snapperd_contexts_path)
    516 
    517 const char *selinux_systemd_contexts_path(void)
    518 {
    519 	return get_path(SYSTEMD_CONTEXTS);
    520 }
    521 
    522 hidden_def(selinux_systemd_contexts_path)
    523 
    524 const char * selinux_booleans_subs_path(void) {
    525 	return get_path(BOOLEAN_SUBS);
    526 }
    527 
    528 hidden_def(selinux_booleans_subs_path)
    529 
    530 const char * selinux_file_context_subs_path(void) {
    531 	return get_path(FILE_CONTEXT_SUBS);
    532 }
    533 
    534 hidden_def(selinux_file_context_subs_path)
    535 
    536 const char * selinux_file_context_subs_dist_path(void) {
    537 	return get_path(FILE_CONTEXT_SUBS_DIST);
    538 }
    539 
    540 hidden_def(selinux_file_context_subs_dist_path)
    541 
    542 const char *selinux_sepgsql_context_path(void)
    543 {
    544 	return get_path(SEPGSQL_CONTEXTS);
    545 }
    546 
    547 hidden_def(selinux_sepgsql_context_path)
    548