• 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 REQUIRESEUSERS "REQUIRESEUSERS="
20 
21 /* Indices for file paths arrays. */
22 #define BINPOLICY         0
23 #define CONTEXTS_DIR      1
24 #define FILE_CONTEXTS     2
25 #define HOMEDIR_CONTEXTS  3
26 #define DEFAULT_CONTEXTS  4
27 #define USER_CONTEXTS     5
28 #define FAILSAFE_CONTEXT  6
29 #define DEFAULT_TYPE      7
30 /* BOOLEANS is deprecated */
31 #define BOOLEANS          8
32 #define MEDIA_CONTEXTS    9
33 #define REMOVABLE_CONTEXT 10
34 #define CUSTOMIZABLE_TYPES    11
35 /* USERS_DIR is deprecated */
36 #define USERS_DIR         12
37 #define SEUSERS           13
38 #define TRANSLATIONS      14
39 #define NETFILTER_CONTEXTS    15
40 #define FILE_CONTEXTS_HOMEDIR 16
41 #define FILE_CONTEXTS_LOCAL 17
42 #define SECURETTY_TYPES   18
43 #define X_CONTEXTS        19
44 #define COLORS            20
45 #define VIRTUAL_DOMAIN    21
46 #define VIRTUAL_IMAGE     22
47 #define FILE_CONTEXT_SUBS 23
48 #define SEPGSQL_CONTEXTS  24
49 #define FILE_CONTEXT_SUBS_DIST 25
50 #define LXC_CONTEXTS      26
51 #define BOOLEAN_SUBS      27
52 #define OPENSSH_CONTEXTS  28
53 #define SYSTEMD_CONTEXTS  29
54 #define SNAPPERD_CONTEXTS 30
55 #define OPENRC_CONTEXTS   31
56 #define NEL               32
57 
58 /* Part of one-time lazy init */
59 static pthread_once_t once = PTHREAD_ONCE_INIT;
60 static void init_selinux_config(void);
61 
62 /* New layout is relative to SELINUXDIR/policytype. */
63 static char *file_paths[NEL];
64 #define L1(l) L2(l)
65 #define L2(l)str##l
66 static const union file_path_suffixes_data {
67 	struct {
68 #define S_(n, s) char L1(__LINE__)[sizeof(s)];
69 #include "file_path_suffixes.h"
70 #undef S_
71 	};
72 	char str[0];
73 } file_path_suffixes_data = {
74 	{
75 #define S_(n, s) s,
76 #include "file_path_suffixes.h"
77 #undef S_
78 	}
79 };
80 static const uint16_t file_path_suffixes_idx[NEL] = {
81 #define S_(n, s) [n] = offsetof(union file_path_suffixes_data, L1(__LINE__)),
82 #include "file_path_suffixes.h"
83 #undef S_
84 };
85 
86 #undef L1
87 #undef L2
88 
selinux_getenforcemode(int * enforce)89 int selinux_getenforcemode(int *enforce)
90 {
91 	int ret = -1;
92 	FILE *cfg = fopen(SELINUXCONFIG, "re");
93 	if (cfg) {
94 		char *buf;
95 		char *tag;
96 		int len = sizeof(SELINUXTAG) - 1;
97 		buf = malloc(selinux_page_size);
98 		if (!buf) {
99 			fclose(cfg);
100 			return -1;
101 		}
102 		while (fgets_unlocked(buf, selinux_page_size, cfg)) {
103 			if (strncmp(buf, SELINUXTAG, len))
104 				continue;
105 			tag = buf+len;
106 			while (isspace(*tag))
107 				tag++;
108 			if (!strncasecmp
109 			    (tag, "enforcing", sizeof("enforcing") - 1)) {
110 				*enforce = 1;
111 				ret = 0;
112 				break;
113 			} else
114 			    if (!strncasecmp
115 				(tag, "permissive",
116 				 sizeof("permissive") - 1)) {
117 				*enforce = 0;
118 				ret = 0;
119 				break;
120 			} else
121 			    if (!strncasecmp
122 				(tag, "disabled",
123 				 sizeof("disabled") - 1)) {
124 				*enforce = -1;
125 				ret = 0;
126 				break;
127 			}
128 		}
129 		fclose(cfg);
130 		free(buf);
131 	}
132 	return ret;
133 }
134 
135 
136 static char *selinux_policytype;
137 
selinux_getpolicytype(char ** type)138 int selinux_getpolicytype(char **type)
139 {
140 	__selinux_once(once, init_selinux_config);
141 	if (!selinux_policytype)
142 		return -1;
143 	*type = strdup(selinux_policytype);
144 	return *type ? 0 : -1;
145 }
146 
147 
setpolicytype(const char * type)148 static int setpolicytype(const char *type)
149 {
150 	free(selinux_policytype);
151 	selinux_policytype = strdup(type);
152 	return selinux_policytype ? 0 : -1;
153 }
154 
155 static char *selinux_policyroot = NULL;
156 static const char *selinux_rootpath = SELINUXDIR;
157 
init_selinux_config(void)158 static void init_selinux_config(void)
159 {
160 	int i, *intptr;
161 	size_t line_len;
162 	ssize_t len;
163 	char *line_buf = NULL, *buf_p, *value, *type = NULL, *end;
164 	FILE *fp;
165 
166 	if (selinux_policyroot)
167 		return;
168 
169 	fp = fopen(SELINUXCONFIG, "re");
170 	if (fp) {
171 		__fsetlocking(fp, FSETLOCKING_BYCALLER);
172 		while ((len = getline(&line_buf, &line_len, fp)) > 0) {
173 			if (line_buf[len - 1] == '\n')
174 				line_buf[len - 1] = 0;
175 			buf_p = line_buf;
176 			while (isspace(*buf_p))
177 				buf_p++;
178 			if (*buf_p == '#' || *buf_p == 0)
179 				continue;
180 
181 			if (!strncasecmp(buf_p, SELINUXTYPETAG,
182 					 sizeof(SELINUXTYPETAG) - 1)) {
183 				buf_p += sizeof(SELINUXTYPETAG) - 1;
184 				while (isspace(*buf_p))
185 					buf_p++;
186 				type = strdup(buf_p);
187 				if (!type) {
188 					free(line_buf);
189 					fclose(fp);
190 					return;
191 				}
192 				end = type + strlen(type) - 1;
193 				while ((end > type) &&
194 				       (isspace(*end) || iscntrl(*end))) {
195 					*end = 0;
196 					end--;
197 				}
198 				if (setpolicytype(type) != 0) {
199 					free(type);
200 					free(line_buf);
201 					fclose(fp);
202 					return;
203 				}
204 				free(type);
205 				continue;
206 			} else if (!strncmp(buf_p, REQUIRESEUSERS,
207 					    sizeof(REQUIRESEUSERS) - 1)) {
208 				value = buf_p + sizeof(REQUIRESEUSERS) - 1;
209 				while (isspace(*value))
210 					value++;
211 				intptr = &require_seusers;
212 			} else {
213 				continue;
214 			}
215 
216 			if (isdigit(*value))
217 				*intptr = atoi(value);
218 			else if (strncasecmp(value, "true", sizeof("true") - 1))
219 				*intptr = 1;
220 			else if (strncasecmp
221 				 (value, "false", sizeof("false") - 1))
222 				*intptr = 0;
223 		}
224 		free(line_buf);
225 		fclose(fp);
226 	}
227 
228 	if (!selinux_policytype && setpolicytype(SELINUXDEFAULT) != 0)
229 		return;
230 
231 	if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, selinux_policytype) == -1)
232 		return;
233 
234 	for (i = 0; i < NEL; i++)
235 		if (asprintf(&file_paths[i], "%s%s",
236 			     selinux_policyroot,
237 			     file_path_suffixes_data.str +
238 			     file_path_suffixes_idx[i])
239 		    == -1)
240 			return;
241 }
242 
243 static void fini_selinux_policyroot(void) __attribute__ ((destructor));
244 
fini_selinux_policyroot(void)245 static void fini_selinux_policyroot(void)
246 {
247 	int i;
248 	free(selinux_policyroot);
249 	selinux_policyroot = NULL;
250 	for (i = 0; i < NEL; i++) {
251 		free(file_paths[i]);
252 		file_paths[i] = NULL;
253 	}
254 	free(selinux_policytype);
255 	selinux_policytype = NULL;
256 }
257 
selinux_reset_config(void)258 void selinux_reset_config(void)
259 {
260 	fini_selinux_policyroot();
261 	init_selinux_config();
262 }
263 
264 
get_path(int idx)265 static const char *get_path(int idx)
266 {
267 	__selinux_once(once, init_selinux_config);
268 	return file_paths[idx];
269 }
270 
selinux_default_type_path(void)271 const char *selinux_default_type_path(void)
272 {
273 	return get_path(DEFAULT_TYPE);
274 }
275 
276 
selinux_policy_root(void)277 const char *selinux_policy_root(void)
278 {
279 	__selinux_once(once, init_selinux_config);
280 	return selinux_policyroot;
281 }
282 
selinux_set_policy_root(const char * path)283 int selinux_set_policy_root(const char *path)
284 {
285 	int i;
286 	char *policy_type = strrchr(path, '/');
287 	if (!policy_type) {
288 		errno = EINVAL;
289 		return -1;
290 	}
291 	policy_type++;
292 
293 	fini_selinux_policyroot();
294 
295 	selinux_policyroot = strdup(path);
296 	if (! selinux_policyroot)
297 		return -1;
298 
299 	if (setpolicytype(policy_type) != 0)
300 		return -1;
301 
302 	for (i = 0; i < NEL; i++)
303 		if (asprintf(&file_paths[i], "%s%s",
304 			     selinux_policyroot,
305 			     file_path_suffixes_data.str +
306 			     file_path_suffixes_idx[i])
307 		    == -1)
308 			return -1;
309 
310 	return 0;
311 }
312 
selinux_path(void)313 const char *selinux_path(void)
314 {
315 	return selinux_rootpath;
316 }
317 
318 
selinux_default_context_path(void)319 const char *selinux_default_context_path(void)
320 {
321 	return get_path(DEFAULT_CONTEXTS);
322 }
323 
324 
selinux_securetty_types_path(void)325 const char *selinux_securetty_types_path(void)
326 {
327 	return get_path(SECURETTY_TYPES);
328 }
329 
330 
selinux_failsafe_context_path(void)331 const char *selinux_failsafe_context_path(void)
332 {
333 	return get_path(FAILSAFE_CONTEXT);
334 }
335 
336 
selinux_removable_context_path(void)337 const char *selinux_removable_context_path(void)
338 {
339 	return get_path(REMOVABLE_CONTEXT);
340 }
341 
342 
selinux_binary_policy_path(void)343 const char *selinux_binary_policy_path(void)
344 {
345 	return get_path(BINPOLICY);
346 }
347 
348 
selinux_current_policy_path(void)349 const char *selinux_current_policy_path(void)
350 {
351 	int rc = 0;
352 	int vers = 0;
353 	static char policy_path[PATH_MAX];
354 
355 	if (selinux_mnt) {
356 		snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt);
357 		if (access(policy_path, F_OK) == 0 ) {
358 			return policy_path;
359 		}
360 	}
361 	vers = security_policyvers();
362 	do {
363 		/* Check prior versions to see if old policy is available */
364 		snprintf(policy_path, sizeof(policy_path), "%s.%d",
365 			 selinux_binary_policy_path(), vers);
366 	} while ((rc = access(policy_path, F_OK)) && --vers > 0);
367 
368 	if (rc) return NULL;
369 	return policy_path;
370 }
371 
372 
selinux_file_context_path(void)373 const char *selinux_file_context_path(void)
374 {
375 	return get_path(FILE_CONTEXTS);
376 }
377 
378 
selinux_homedir_context_path(void)379 const char *selinux_homedir_context_path(void)
380 {
381 	return get_path(HOMEDIR_CONTEXTS);
382 }
383 
384 
selinux_media_context_path(void)385 const char *selinux_media_context_path(void)
386 {
387 	return get_path(MEDIA_CONTEXTS);
388 }
389 
390 
selinux_customizable_types_path(void)391 const char *selinux_customizable_types_path(void)
392 {
393 	return get_path(CUSTOMIZABLE_TYPES);
394 }
395 
396 
selinux_contexts_path(void)397 const char *selinux_contexts_path(void)
398 {
399 	return get_path(CONTEXTS_DIR);
400 }
401 
selinux_user_contexts_path(void)402 const char *selinux_user_contexts_path(void)
403 {
404 	return get_path(USER_CONTEXTS);
405 }
406 
407 
408 /* Deprecated as local policy booleans no longer supported. */
selinux_booleans_path(void)409 const char *selinux_booleans_path(void)
410 {
411 	return get_path(BOOLEANS);
412 }
413 
414 
415 /* Deprecated as no longer supported. */
selinux_users_path(void)416 const char *selinux_users_path(void)
417 {
418 	return get_path(USERS_DIR);
419 }
420 
421 
selinux_usersconf_path(void)422 const char *selinux_usersconf_path(void)
423 {
424 	return get_path(SEUSERS);
425 }
426 
427 
selinux_translations_path(void)428 const char *selinux_translations_path(void)
429 {
430 	return get_path(TRANSLATIONS);
431 }
432 
433 
selinux_colors_path(void)434 const char *selinux_colors_path(void)
435 {
436 	return get_path(COLORS);
437 }
438 
439 
selinux_netfilter_context_path(void)440 const char *selinux_netfilter_context_path(void)
441 {
442 	return get_path(NETFILTER_CONTEXTS);
443 }
444 
445 
selinux_file_context_homedir_path(void)446 const char *selinux_file_context_homedir_path(void)
447 {
448 	return get_path(FILE_CONTEXTS_HOMEDIR);
449 }
450 
451 
selinux_file_context_local_path(void)452 const char *selinux_file_context_local_path(void)
453 {
454 	return get_path(FILE_CONTEXTS_LOCAL);
455 }
456 
457 
selinux_x_context_path(void)458 const char *selinux_x_context_path(void)
459 {
460 	return get_path(X_CONTEXTS);
461 }
462 
463 
selinux_virtual_domain_context_path(void)464 const char *selinux_virtual_domain_context_path(void)
465 {
466 	return get_path(VIRTUAL_DOMAIN);
467 }
468 
469 
selinux_virtual_image_context_path(void)470 const char *selinux_virtual_image_context_path(void)
471 {
472 	return get_path(VIRTUAL_IMAGE);
473 }
474 
475 
selinux_lxc_contexts_path(void)476 const char *selinux_lxc_contexts_path(void)
477 {
478 	return get_path(LXC_CONTEXTS);
479 }
480 
481 
selinux_openrc_contexts_path(void)482 const char *selinux_openrc_contexts_path(void)
483 {
484     return get_path(OPENRC_CONTEXTS);
485 }
486 
487 
selinux_openssh_contexts_path(void)488 const char *selinux_openssh_contexts_path(void)
489 {
490     return get_path(OPENSSH_CONTEXTS);
491 }
492 
493 
selinux_snapperd_contexts_path(void)494 const char *selinux_snapperd_contexts_path(void)
495 {
496     return get_path(SNAPPERD_CONTEXTS);
497 }
498 
499 
selinux_systemd_contexts_path(void)500 const char *selinux_systemd_contexts_path(void)
501 {
502 	return get_path(SYSTEMD_CONTEXTS);
503 }
504 
505 
selinux_booleans_subs_path(void)506 const char * selinux_booleans_subs_path(void) {
507 	return get_path(BOOLEAN_SUBS);
508 }
509 
510 
selinux_file_context_subs_path(void)511 const char * selinux_file_context_subs_path(void) {
512 	return get_path(FILE_CONTEXT_SUBS);
513 }
514 
515 
selinux_file_context_subs_dist_path(void)516 const char * selinux_file_context_subs_dist_path(void) {
517 	return get_path(FILE_CONTEXT_SUBS_DIST);
518 }
519 
520 
selinux_sepgsql_context_path(void)521 const char *selinux_sepgsql_context_path(void)
522 {
523 	return get_path(SEPGSQL_CONTEXTS);
524 }
525 
526