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 				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