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 SELINUXDIR "/etc/selinux/"
     17 #define SELINUXCONFIG SELINUXDIR "config"
     18 #define SELINUXDEFAULT "targeted"
     19 #define SELINUXTYPETAG "SELINUXTYPE="
     20 #define SELINUXTAG "SELINUX="
     21 #define SETLOCALDEFS "SETLOCALDEFS="
     22 #define REQUIRESEUSERS "REQUIRESEUSERS="
     23 
     24 /* Indices for file paths arrays. */
     25 #define BINPOLICY         0
     26 #define CONTEXTS_DIR      1
     27 #define FILE_CONTEXTS     2
     28 #define HOMEDIR_CONTEXTS  3
     29 #define DEFAULT_CONTEXTS  4
     30 #define USER_CONTEXTS     5
     31 #define FAILSAFE_CONTEXT  6
     32 #define DEFAULT_TYPE      7
     33 #define BOOLEANS          8
     34 #define MEDIA_CONTEXTS    9
     35 #define REMOVABLE_CONTEXT 10
     36 #define CUSTOMIZABLE_TYPES    11
     37 #define USERS_DIR         12
     38 #define SEUSERS           13
     39 #define TRANSLATIONS      14
     40 #define NETFILTER_CONTEXTS    15
     41 #define FILE_CONTEXTS_HOMEDIR 16
     42 #define FILE_CONTEXTS_LOCAL 17
     43 #define SECURETTY_TYPES   18
     44 #define X_CONTEXTS        19
     45 #define COLORS            20
     46 #define VIRTUAL_DOMAIN    21
     47 #define VIRTUAL_IMAGE     22
     48 #define FILE_CONTEXT_SUBS 23
     49 #define SEPGSQL_CONTEXTS  24
     50 #define FILE_CONTEXT_SUBS_DIST 25
     51 #define LXC_CONTEXTS      26
     52 #define BOOLEAN_SUBS      27
     53 #define SYSTEMD_CONTEXTS  28
     54 #define NEL               29
     55 
     56 /* Part of one-time lazy init */
     57 static pthread_once_t once = PTHREAD_ONCE_INIT;
     58 static void init_selinux_config(void);
     59 
     60 /* New layout is relative to SELINUXDIR/policytype. */
     61 static char *file_paths[NEL];
     62 #define L1(l) L2(l)
     63 #define L2(l)str##l
     64 static const union file_path_suffixes_data {
     65 	struct {
     66 #define S_(n, s) char L1(__LINE__)[sizeof(s)];
     67 #include "file_path_suffixes.h"
     68 #undef S_
     69 	};
     70 	char str[0];
     71 } file_path_suffixes_data = {
     72 	{
     73 #define S_(n, s) s,
     74 #include "file_path_suffixes.h"
     75 #undef S_
     76 	}
     77 };
     78 static const uint16_t file_path_suffixes_idx[NEL] = {
     79 #define S_(n, s) [n] = offsetof(union file_path_suffixes_data, L1(__LINE__)),
     80 #include "file_path_suffixes.h"
     81 #undef S_
     82 };
     83 
     84 #undef L1
     85 #undef L2
     86 
     87 int selinux_getenforcemode(int *enforce)
     88 {
     89 	int ret = -1;
     90 	FILE *cfg = fopen(SELINUXCONFIG, "r");
     91 	if (cfg) {
     92 		char *buf;
     93 		int len = sizeof(SELINUXTAG) - 1;
     94 		buf = malloc(selinux_page_size);
     95 		if (!buf) {
     96 			fclose(cfg);
     97 			return -1;
     98 		}
     99 		while (fgets_unlocked(buf, selinux_page_size, cfg)) {
    100 			if (strncmp(buf, SELINUXTAG, len))
    101 				continue;
    102 			if (!strncasecmp
    103 			    (buf + len, "enforcing", sizeof("enforcing") - 1)) {
    104 				*enforce = 1;
    105 				ret = 0;
    106 				break;
    107 			} else
    108 			    if (!strncasecmp
    109 				(buf + len, "permissive",
    110 				 sizeof("permissive") - 1)) {
    111 				*enforce = 0;
    112 				ret = 0;
    113 				break;
    114 			} else
    115 			    if (!strncasecmp
    116 				(buf + len, "disabled",
    117 				 sizeof("disabled") - 1)) {
    118 				*enforce = -1;
    119 				ret = 0;
    120 				break;
    121 			}
    122 		}
    123 		fclose(cfg);
    124 		free(buf);
    125 	}
    126 	return ret;
    127 }
    128 
    129 hidden_def(selinux_getenforcemode)
    130 
    131 static char *selinux_policytype;
    132 
    133 int selinux_getpolicytype(char **type)
    134 {
    135 	__selinux_once(once, init_selinux_config);
    136 	if (!selinux_policytype)
    137 		return -1;
    138 	*type = strdup(selinux_policytype);
    139 	return *type ? 0 : -1;
    140 }
    141 
    142 hidden_def(selinux_getpolicytype)
    143 
    144 static int setpolicytype(const char *type)
    145 {
    146 	free(selinux_policytype);
    147 	selinux_policytype = strdup(type);
    148 	return selinux_policytype ? 0 : -1;
    149 }
    150 
    151 static char *selinux_policyroot = NULL;
    152 static const char *selinux_rootpath = SELINUXDIR;
    153 
    154 static void init_selinux_config(void)
    155 {
    156 	int i, *intptr;
    157 	size_t line_len;
    158 	ssize_t len;
    159 	char *line_buf = NULL, *buf_p, *value, *type = NULL, *end;
    160 	FILE *fp;
    161 
    162 	if (selinux_policyroot)
    163 		return;
    164 
    165 	fp = fopen(SELINUXCONFIG, "r");
    166 	if (fp) {
    167 		__fsetlocking(fp, FSETLOCKING_BYCALLER);
    168 		while ((len = getline(&line_buf, &line_len, fp)) > 0) {
    169 			if (line_buf[len - 1] == '\n')
    170 				line_buf[len - 1] = 0;
    171 			buf_p = line_buf;
    172 			while (isspace(*buf_p))
    173 				buf_p++;
    174 			if (*buf_p == '#' || *buf_p == 0)
    175 				continue;
    176 
    177 			if (!strncasecmp(buf_p, SELINUXTYPETAG,
    178 					 sizeof(SELINUXTYPETAG) - 1)) {
    179 				selinux_policytype = type =
    180 				    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 				continue;
    190 			} else if (!strncmp(buf_p, SETLOCALDEFS,
    191 					    sizeof(SETLOCALDEFS) - 1)) {
    192 				value = buf_p + sizeof(SETLOCALDEFS) - 1;
    193 				intptr = &load_setlocaldefs;
    194 			} else if (!strncmp(buf_p, REQUIRESEUSERS,
    195 					    sizeof(REQUIRESEUSERS) - 1)) {
    196 				value = buf_p + sizeof(REQUIRESEUSERS) - 1;
    197 				intptr = &require_seusers;
    198 			} else {
    199 				continue;
    200 			}
    201 
    202 			if (isdigit(*value))
    203 				*intptr = atoi(value);
    204 			else if (strncasecmp(value, "true", sizeof("true") - 1))
    205 				*intptr = 1;
    206 			else if (strncasecmp
    207 				 (value, "false", sizeof("false") - 1))
    208 				*intptr = 0;
    209 		}
    210 		free(line_buf);
    211 		fclose(fp);
    212 	}
    213 
    214 	if (!type) {
    215 		selinux_policytype = type = strdup(SELINUXDEFAULT);
    216 		if (!type)
    217 			return;
    218 	}
    219 
    220 	if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, type) == -1)
    221 		return;
    222 
    223 	for (i = 0; i < NEL; i++)
    224 		if (asprintf(&file_paths[i], "%s%s",
    225 			     selinux_policyroot,
    226 			     file_path_suffixes_data.str +
    227 			     file_path_suffixes_idx[i])
    228 		    == -1)
    229 			return;
    230 }
    231 
    232 static void fini_selinux_policyroot(void) __attribute__ ((destructor));
    233 
    234 static void fini_selinux_policyroot(void)
    235 {
    236 	int i;
    237 	free(selinux_policyroot);
    238 	selinux_policyroot = NULL;
    239 	for (i = 0; i < NEL; i++) {
    240 		free(file_paths[i]);
    241 		file_paths[i] = NULL;
    242 	}
    243 	free(selinux_policytype);
    244 	selinux_policytype = NULL;
    245 }
    246 
    247 void selinux_reset_config(void)
    248 {
    249 	fini_selinux_policyroot();
    250 	init_selinux_config();
    251 }
    252 
    253 hidden_def(selinux_reset_config)
    254 
    255 static const char *get_path(int idx)
    256 {
    257 	__selinux_once(once, init_selinux_config);
    258 	return file_paths[idx];
    259 }
    260 
    261 const char *selinux_default_type_path(void)
    262 {
    263 	return get_path(DEFAULT_TYPE);
    264 }
    265 
    266 hidden_def(selinux_default_type_path)
    267 
    268 const char *selinux_policy_root(void)
    269 {
    270 	__selinux_once(once, init_selinux_config);
    271 	return selinux_policyroot;
    272 }
    273 
    274 int selinux_set_policy_root(const char *path)
    275 {
    276 	int i;
    277 	char *policy_type = strrchr(path, '/');
    278 	if (!policy_type) {
    279 		errno = EINVAL;
    280 		return -1;
    281 	}
    282 	policy_type++;
    283 
    284 	fini_selinuxmnt();
    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_systemd_contexts_path(void)
    497 {
    498 	return get_path(SYSTEMD_CONTEXTS);
    499 }
    500 
    501 hidden_def(selinux_systemd_contexts_path)
    502 
    503 const char * selinux_booleans_subs_path(void) {
    504 	return get_path(BOOLEAN_SUBS);
    505 }
    506 
    507 hidden_def(selinux_booleans_subs_path)
    508 
    509 const char * selinux_file_context_subs_path(void) {
    510 	return get_path(FILE_CONTEXT_SUBS);
    511 }
    512 
    513 hidden_def(selinux_file_context_subs_path)
    514 
    515 const char * selinux_file_context_subs_dist_path(void) {
    516 	return get_path(FILE_CONTEXT_SUBS_DIST);
    517 }
    518 
    519 hidden_def(selinux_file_context_subs_dist_path)
    520 
    521 const char *selinux_sepgsql_context_path(void)
    522 {
    523 	return get_path(SEPGSQL_CONTEXTS);
    524 }
    525 
    526 hidden_def(selinux_sepgsql_context_path)
    527