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