• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
selinux_getenforcemode(int * enforce)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 
hidden_def(selinux_getenforcemode)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 
hidden_def(selinux_getpolicytype)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 
init_selinux_config(void)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 
fini_selinux_policyroot(void)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 
selinux_reset_config(void)249 void selinux_reset_config(void)
250 {
251 	fini_selinux_policyroot();
252 	init_selinux_config();
253 }
254 
hidden_def(selinux_reset_config)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 
selinux_default_type_path(void)263 const char *selinux_default_type_path(void)
264 {
265 	return get_path(DEFAULT_TYPE);
266 }
267 
hidden_def(selinux_default_type_path)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 
selinux_set_policy_root(const char * path)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 
selinux_path(void)306 const char *selinux_path(void)
307 {
308 	return selinux_rootpath;
309 }
310 
hidden_def(selinux_path)311 hidden_def(selinux_path)
312 
313 const char *selinux_default_context_path(void)
314 {
315 	return get_path(DEFAULT_CONTEXTS);
316 }
317 
hidden_def(selinux_default_context_path)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 
hidden_def(selinux_securetty_types_path)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 
hidden_def(selinux_failsafe_context_path)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 
hidden_def(selinux_removable_context_path)339 hidden_def(selinux_removable_context_path)
340 
341 const char *selinux_binary_policy_path(void)
342 {
343 	return get_path(BINPOLICY);
344 }
345 
hidden_def(selinux_binary_policy_path)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 
hidden_def(selinux_current_policy_path)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 
hidden_def(selinux_file_context_path)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 
hidden_def(selinux_homedir_context_path)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 
hidden_def(selinux_media_context_path)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 
hidden_def(selinux_customizable_types_path)399 hidden_def(selinux_customizable_types_path)
400 
401 const char *selinux_contexts_path(void)
402 {
403 	return get_path(CONTEXTS_DIR);
404 }
405 
selinux_user_contexts_path(void)406 const char *selinux_user_contexts_path(void)
407 {
408 	return get_path(USER_CONTEXTS);
409 }
410 
hidden_def(selinux_user_contexts_path)411 hidden_def(selinux_user_contexts_path)
412 
413 const char *selinux_booleans_path(void)
414 {
415 	return get_path(BOOLEANS);
416 }
417 
hidden_def(selinux_booleans_path)418 hidden_def(selinux_booleans_path)
419 
420 const char *selinux_users_path(void)
421 {
422 	return get_path(USERS_DIR);
423 }
424 
hidden_def(selinux_users_path)425 hidden_def(selinux_users_path)
426 
427 const char *selinux_usersconf_path(void)
428 {
429 	return get_path(SEUSERS);
430 }
431 
hidden_def(selinux_usersconf_path)432 hidden_def(selinux_usersconf_path)
433 
434 const char *selinux_translations_path(void)
435 {
436 	return get_path(TRANSLATIONS);
437 }
438 
hidden_def(selinux_translations_path)439 hidden_def(selinux_translations_path)
440 
441 const char *selinux_colors_path(void)
442 {
443 	return get_path(COLORS);
444 }
445 
hidden_def(selinux_colors_path)446 hidden_def(selinux_colors_path)
447 
448 const char *selinux_netfilter_context_path(void)
449 {
450 	return get_path(NETFILTER_CONTEXTS);
451 }
452 
hidden_def(selinux_netfilter_context_path)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 
hidden_def(selinux_file_context_homedir_path)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 
hidden_def(selinux_file_context_local_path)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 
hidden_def(selinux_x_context_path)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 
hidden_def(selinux_virtual_domain_context_path)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 
hidden_def(selinux_virtual_image_context_path)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 
hidden_def(selinux_lxc_contexts_path)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 
hidden_def(selinux_openrc_contexts_path)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 
hidden_def(selinux_openssh_contexts_path)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 
hidden_def(selinux_snapperd_contexts_path)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 
hidden_def(selinux_systemd_contexts_path)523 hidden_def(selinux_systemd_contexts_path)
524 
525 const char * selinux_booleans_subs_path(void) {
526 	return get_path(BOOLEAN_SUBS);
527 }
528 
hidden_def(selinux_booleans_subs_path)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 
hidden_def(selinux_file_context_subs_path)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 
hidden_def(selinux_file_context_subs_dist_path)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