• 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 		int len = sizeof(SELINUXTAG) - 1;
96 		buf = malloc(selinux_page_size);
97 		if (!buf) {
98 			fclose(cfg);
99 			return -1;
100 		}
101 		while (fgets_unlocked(buf, selinux_page_size, cfg)) {
102 			if (strncmp(buf, SELINUXTAG, len))
103 				continue;
104 			if (!strncasecmp
105 			    (buf + len, "enforcing", sizeof("enforcing") - 1)) {
106 				*enforce = 1;
107 				ret = 0;
108 				break;
109 			} else
110 			    if (!strncasecmp
111 				(buf + len, "permissive",
112 				 sizeof("permissive") - 1)) {
113 				*enforce = 0;
114 				ret = 0;
115 				break;
116 			} else
117 			    if (!strncasecmp
118 				(buf + len, "disabled",
119 				 sizeof("disabled") - 1)) {
120 				*enforce = -1;
121 				ret = 0;
122 				break;
123 			}
124 		}
125 		fclose(cfg);
126 		free(buf);
127 	}
128 	return ret;
129 }
130 
131 
132 static char *selinux_policytype;
133 
selinux_getpolicytype(char ** type)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 
setpolicytype(const char * type)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 
init_selinux_config(void)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, "re");
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 				type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
180 				if (!type) {
181 					free(line_buf);
182 					fclose(fp);
183 					return;
184 				}
185 				end = type + strlen(type) - 1;
186 				while ((end > type) &&
187 				       (isspace(*end) || iscntrl(*end))) {
188 					*end = 0;
189 					end--;
190 				}
191 				if (setpolicytype(type) != 0) {
192 					free(type);
193 					free(line_buf);
194 					fclose(fp);
195 					return;
196 				}
197 				free(type);
198 				continue;
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 
255 
get_path(int idx)256 static const char *get_path(int idx)
257 {
258 	__selinux_once(once, init_selinux_config);
259 	return file_paths[idx];
260 }
261 
selinux_default_type_path(void)262 const char *selinux_default_type_path(void)
263 {
264 	return get_path(DEFAULT_TYPE);
265 }
266 
267 
selinux_policy_root(void)268 const char *selinux_policy_root(void)
269 {
270 	__selinux_once(once, init_selinux_config);
271 	return selinux_policyroot;
272 }
273 
selinux_set_policy_root(const char * path)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_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 
selinux_path(void)304 const char *selinux_path(void)
305 {
306 	return selinux_rootpath;
307 }
308 
309 
selinux_default_context_path(void)310 const char *selinux_default_context_path(void)
311 {
312 	return get_path(DEFAULT_CONTEXTS);
313 }
314 
315 
selinux_securetty_types_path(void)316 const char *selinux_securetty_types_path(void)
317 {
318 	return get_path(SECURETTY_TYPES);
319 }
320 
321 
selinux_failsafe_context_path(void)322 const char *selinux_failsafe_context_path(void)
323 {
324 	return get_path(FAILSAFE_CONTEXT);
325 }
326 
327 
selinux_removable_context_path(void)328 const char *selinux_removable_context_path(void)
329 {
330 	return get_path(REMOVABLE_CONTEXT);
331 }
332 
333 
selinux_binary_policy_path(void)334 const char *selinux_binary_policy_path(void)
335 {
336 	return get_path(BINPOLICY);
337 }
338 
339 
selinux_current_policy_path(void)340 const char *selinux_current_policy_path(void)
341 {
342 	int rc = 0;
343 	int vers = 0;
344 	static char policy_path[PATH_MAX];
345 
346 	if (selinux_mnt) {
347 		snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt);
348 		if (access(policy_path, F_OK) == 0 ) {
349 			return policy_path;
350 		}
351 	}
352 	vers = security_policyvers();
353 	do {
354 		/* Check prior versions to see if old policy is available */
355 		snprintf(policy_path, sizeof(policy_path), "%s.%d",
356 			 selinux_binary_policy_path(), vers);
357 	} while ((rc = access(policy_path, F_OK)) && --vers > 0);
358 
359 	if (rc) return NULL;
360 	return policy_path;
361 }
362 
363 
selinux_file_context_path(void)364 const char *selinux_file_context_path(void)
365 {
366 	return get_path(FILE_CONTEXTS);
367 }
368 
369 
selinux_homedir_context_path(void)370 const char *selinux_homedir_context_path(void)
371 {
372 	return get_path(HOMEDIR_CONTEXTS);
373 }
374 
375 
selinux_media_context_path(void)376 const char *selinux_media_context_path(void)
377 {
378 	return get_path(MEDIA_CONTEXTS);
379 }
380 
381 
selinux_customizable_types_path(void)382 const char *selinux_customizable_types_path(void)
383 {
384 	return get_path(CUSTOMIZABLE_TYPES);
385 }
386 
387 
selinux_contexts_path(void)388 const char *selinux_contexts_path(void)
389 {
390 	return get_path(CONTEXTS_DIR);
391 }
392 
selinux_user_contexts_path(void)393 const char *selinux_user_contexts_path(void)
394 {
395 	return get_path(USER_CONTEXTS);
396 }
397 
398 
399 /* Deprecated as local policy booleans no longer supported. */
selinux_booleans_path(void)400 const char *selinux_booleans_path(void)
401 {
402 	return get_path(BOOLEANS);
403 }
404 
405 
406 /* Deprecated as no longer supported. */
selinux_users_path(void)407 const char *selinux_users_path(void)
408 {
409 	return get_path(USERS_DIR);
410 }
411 
412 
selinux_usersconf_path(void)413 const char *selinux_usersconf_path(void)
414 {
415 	return get_path(SEUSERS);
416 }
417 
418 
selinux_translations_path(void)419 const char *selinux_translations_path(void)
420 {
421 	return get_path(TRANSLATIONS);
422 }
423 
424 
selinux_colors_path(void)425 const char *selinux_colors_path(void)
426 {
427 	return get_path(COLORS);
428 }
429 
430 
selinux_netfilter_context_path(void)431 const char *selinux_netfilter_context_path(void)
432 {
433 	return get_path(NETFILTER_CONTEXTS);
434 }
435 
436 
selinux_file_context_homedir_path(void)437 const char *selinux_file_context_homedir_path(void)
438 {
439 	return get_path(FILE_CONTEXTS_HOMEDIR);
440 }
441 
442 
selinux_file_context_local_path(void)443 const char *selinux_file_context_local_path(void)
444 {
445 	return get_path(FILE_CONTEXTS_LOCAL);
446 }
447 
448 
selinux_x_context_path(void)449 const char *selinux_x_context_path(void)
450 {
451 	return get_path(X_CONTEXTS);
452 }
453 
454 
selinux_virtual_domain_context_path(void)455 const char *selinux_virtual_domain_context_path(void)
456 {
457 	return get_path(VIRTUAL_DOMAIN);
458 }
459 
460 
selinux_virtual_image_context_path(void)461 const char *selinux_virtual_image_context_path(void)
462 {
463 	return get_path(VIRTUAL_IMAGE);
464 }
465 
466 
selinux_lxc_contexts_path(void)467 const char *selinux_lxc_contexts_path(void)
468 {
469 	return get_path(LXC_CONTEXTS);
470 }
471 
472 
selinux_openrc_contexts_path(void)473 const char *selinux_openrc_contexts_path(void)
474 {
475     return get_path(OPENRC_CONTEXTS);
476 }
477 
478 
selinux_openssh_contexts_path(void)479 const char *selinux_openssh_contexts_path(void)
480 {
481     return get_path(OPENSSH_CONTEXTS);
482 }
483 
484 
selinux_snapperd_contexts_path(void)485 const char *selinux_snapperd_contexts_path(void)
486 {
487     return get_path(SNAPPERD_CONTEXTS);
488 }
489 
490 
selinux_systemd_contexts_path(void)491 const char *selinux_systemd_contexts_path(void)
492 {
493 	return get_path(SYSTEMD_CONTEXTS);
494 }
495 
496 
selinux_booleans_subs_path(void)497 const char * selinux_booleans_subs_path(void) {
498 	return get_path(BOOLEAN_SUBS);
499 }
500 
501 
selinux_file_context_subs_path(void)502 const char * selinux_file_context_subs_path(void) {
503 	return get_path(FILE_CONTEXT_SUBS);
504 }
505 
506 
selinux_file_context_subs_dist_path(void)507 const char * selinux_file_context_subs_dist_path(void) {
508 	return get_path(FILE_CONTEXT_SUBS_DIST);
509 }
510 
511 
selinux_sepgsql_context_path(void)512 const char *selinux_sepgsql_context_path(void)
513 {
514 	return get_path(SEPGSQL_CONTEXTS);
515 }
516 
517