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
hidden_def(selinux_getenforcemode)131 hidden_def(selinux_getenforcemode)
132
133 static char *selinux_policytype;
134
135 int selinux_getpolicytype(char **type)
136 {
137 __selinux_once(once, init_selinux_config);
138 if (!selinux_policytype)
139 return -1;
140 *type = strdup(selinux_policytype);
141 return *type ? 0 : -1;
142 }
143
hidden_def(selinux_getpolicytype)144 hidden_def(selinux_getpolicytype)
145
146 static int setpolicytype(const char *type)
147 {
148 free(selinux_policytype);
149 selinux_policytype = strdup(type);
150 return selinux_policytype ? 0 : -1;
151 }
152
153 static char *selinux_policyroot = NULL;
154 static const char *selinux_rootpath = SELINUXDIR;
155
init_selinux_config(void)156 static void init_selinux_config(void)
157 {
158 int i, *intptr;
159 size_t line_len;
160 ssize_t len;
161 char *line_buf = NULL, *buf_p, *value, *type = NULL, *end;
162 FILE *fp;
163
164 if (selinux_policyroot)
165 return;
166
167 fp = fopen(SELINUXCONFIG, "re");
168 if (fp) {
169 __fsetlocking(fp, FSETLOCKING_BYCALLER);
170 while ((len = getline(&line_buf, &line_len, fp)) > 0) {
171 if (line_buf[len - 1] == '\n')
172 line_buf[len - 1] = 0;
173 buf_p = line_buf;
174 while (isspace(*buf_p))
175 buf_p++;
176 if (*buf_p == '#' || *buf_p == 0)
177 continue;
178
179 if (!strncasecmp(buf_p, SELINUXTYPETAG,
180 sizeof(SELINUXTYPETAG) - 1)) {
181 type = strdup(buf_p + sizeof(SELINUXTYPETAG) - 1);
182 if (!type)
183 return;
184 end = type + strlen(type) - 1;
185 while ((end > type) &&
186 (isspace(*end) || iscntrl(*end))) {
187 *end = 0;
188 end--;
189 }
190 if (setpolicytype(type) != 0) {
191 free(type);
192 return;
193 }
194 free(type);
195 continue;
196 } else if (!strncmp(buf_p, REQUIRESEUSERS,
197 sizeof(REQUIRESEUSERS) - 1)) {
198 value = buf_p + sizeof(REQUIRESEUSERS) - 1;
199 intptr = &require_seusers;
200 } else {
201 continue;
202 }
203
204 if (isdigit(*value))
205 *intptr = atoi(value);
206 else if (strncasecmp(value, "true", sizeof("true") - 1))
207 *intptr = 1;
208 else if (strncasecmp
209 (value, "false", sizeof("false") - 1))
210 *intptr = 0;
211 }
212 free(line_buf);
213 fclose(fp);
214 }
215
216 if (!selinux_policytype && setpolicytype(SELINUXDEFAULT) != 0)
217 return;
218
219 if (asprintf(&selinux_policyroot, "%s%s", SELINUXDIR, selinux_policytype) == -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
fini_selinux_policyroot(void)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
selinux_reset_config(void)246 void selinux_reset_config(void)
247 {
248 fini_selinux_policyroot();
249 init_selinux_config();
250 }
251
hidden_def(selinux_reset_config)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
selinux_default_type_path(void)260 const char *selinux_default_type_path(void)
261 {
262 return get_path(DEFAULT_TYPE);
263 }
264
hidden_def(selinux_default_type_path)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
selinux_set_policy_root(const char * path)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_selinux_policyroot();
284
285 selinux_policyroot = strdup(path);
286 if (! selinux_policyroot)
287 return -1;
288
289 if (setpolicytype(policy_type) != 0)
290 return -1;
291
292 for (i = 0; i < NEL; i++)
293 if (asprintf(&file_paths[i], "%s%s",
294 selinux_policyroot,
295 file_path_suffixes_data.str +
296 file_path_suffixes_idx[i])
297 == -1)
298 return -1;
299
300 return 0;
301 }
302
selinux_path(void)303 const char *selinux_path(void)
304 {
305 return selinux_rootpath;
306 }
307
hidden_def(selinux_path)308 hidden_def(selinux_path)
309
310 const char *selinux_default_context_path(void)
311 {
312 return get_path(DEFAULT_CONTEXTS);
313 }
314
hidden_def(selinux_default_context_path)315 hidden_def(selinux_default_context_path)
316
317 const char *selinux_securetty_types_path(void)
318 {
319 return get_path(SECURETTY_TYPES);
320 }
321
hidden_def(selinux_securetty_types_path)322 hidden_def(selinux_securetty_types_path)
323
324 const char *selinux_failsafe_context_path(void)
325 {
326 return get_path(FAILSAFE_CONTEXT);
327 }
328
hidden_def(selinux_failsafe_context_path)329 hidden_def(selinux_failsafe_context_path)
330
331 const char *selinux_removable_context_path(void)
332 {
333 return get_path(REMOVABLE_CONTEXT);
334 }
335
hidden_def(selinux_removable_context_path)336 hidden_def(selinux_removable_context_path)
337
338 const char *selinux_binary_policy_path(void)
339 {
340 return get_path(BINPOLICY);
341 }
342
hidden_def(selinux_binary_policy_path)343 hidden_def(selinux_binary_policy_path)
344
345 const char *selinux_current_policy_path(void)
346 {
347 int rc = 0;
348 int vers = 0;
349 static char policy_path[PATH_MAX];
350
351 if (selinux_mnt) {
352 snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt);
353 if (access(policy_path, F_OK) == 0 ) {
354 return policy_path;
355 }
356 }
357 vers = security_policyvers();
358 do {
359 /* Check prior versions to see if old policy is available */
360 snprintf(policy_path, sizeof(policy_path), "%s.%d",
361 selinux_binary_policy_path(), vers);
362 } while ((rc = access(policy_path, F_OK)) && --vers > 0);
363
364 if (rc) return NULL;
365 return policy_path;
366 }
367
hidden_def(selinux_current_policy_path)368 hidden_def(selinux_current_policy_path)
369
370 const char *selinux_file_context_path(void)
371 {
372 return get_path(FILE_CONTEXTS);
373 }
374
hidden_def(selinux_file_context_path)375 hidden_def(selinux_file_context_path)
376
377 const char *selinux_homedir_context_path(void)
378 {
379 return get_path(HOMEDIR_CONTEXTS);
380 }
381
hidden_def(selinux_homedir_context_path)382 hidden_def(selinux_homedir_context_path)
383
384 const char *selinux_media_context_path(void)
385 {
386 return get_path(MEDIA_CONTEXTS);
387 }
388
hidden_def(selinux_media_context_path)389 hidden_def(selinux_media_context_path)
390
391 const char *selinux_customizable_types_path(void)
392 {
393 return get_path(CUSTOMIZABLE_TYPES);
394 }
395
hidden_def(selinux_customizable_types_path)396 hidden_def(selinux_customizable_types_path)
397
398 const char *selinux_contexts_path(void)
399 {
400 return get_path(CONTEXTS_DIR);
401 }
402
selinux_user_contexts_path(void)403 const char *selinux_user_contexts_path(void)
404 {
405 return get_path(USER_CONTEXTS);
406 }
407
hidden_def(selinux_user_contexts_path)408 hidden_def(selinux_user_contexts_path)
409
410 /* Deprecated as local policy booleans no longer supported. */
411 const char *selinux_booleans_path(void)
412 {
413 return get_path(BOOLEANS);
414 }
415
hidden_def(selinux_booleans_path)416 hidden_def(selinux_booleans_path)
417
418 /* Deprecated as no longer supported. */
419 const char *selinux_users_path(void)
420 {
421 return get_path(USERS_DIR);
422 }
423
hidden_def(selinux_users_path)424 hidden_def(selinux_users_path)
425
426 const char *selinux_usersconf_path(void)
427 {
428 return get_path(SEUSERS);
429 }
430
hidden_def(selinux_usersconf_path)431 hidden_def(selinux_usersconf_path)
432
433 const char *selinux_translations_path(void)
434 {
435 return get_path(TRANSLATIONS);
436 }
437
hidden_def(selinux_translations_path)438 hidden_def(selinux_translations_path)
439
440 const char *selinux_colors_path(void)
441 {
442 return get_path(COLORS);
443 }
444
hidden_def(selinux_colors_path)445 hidden_def(selinux_colors_path)
446
447 const char *selinux_netfilter_context_path(void)
448 {
449 return get_path(NETFILTER_CONTEXTS);
450 }
451
hidden_def(selinux_netfilter_context_path)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
hidden_def(selinux_file_context_homedir_path)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
hidden_def(selinux_file_context_local_path)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
hidden_def(selinux_x_context_path)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
hidden_def(selinux_virtual_domain_context_path)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
hidden_def(selinux_virtual_image_context_path)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
hidden_def(selinux_lxc_contexts_path)494 hidden_def(selinux_lxc_contexts_path)
495
496 const char *selinux_openrc_contexts_path(void)
497 {
498 return get_path(OPENRC_CONTEXTS);
499 }
500
hidden_def(selinux_openrc_contexts_path)501 hidden_def(selinux_openrc_contexts_path)
502
503 const char *selinux_openssh_contexts_path(void)
504 {
505 return get_path(OPENSSH_CONTEXTS);
506 }
507
hidden_def(selinux_openssh_contexts_path)508 hidden_def(selinux_openssh_contexts_path)
509
510 const char *selinux_snapperd_contexts_path(void)
511 {
512 return get_path(SNAPPERD_CONTEXTS);
513 }
514
hidden_def(selinux_snapperd_contexts_path)515 hidden_def(selinux_snapperd_contexts_path)
516
517 const char *selinux_systemd_contexts_path(void)
518 {
519 return get_path(SYSTEMD_CONTEXTS);
520 }
521
hidden_def(selinux_systemd_contexts_path)522 hidden_def(selinux_systemd_contexts_path)
523
524 const char * selinux_booleans_subs_path(void) {
525 return get_path(BOOLEAN_SUBS);
526 }
527
hidden_def(selinux_booleans_subs_path)528 hidden_def(selinux_booleans_subs_path)
529
530 const char * selinux_file_context_subs_path(void) {
531 return get_path(FILE_CONTEXT_SUBS);
532 }
533
hidden_def(selinux_file_context_subs_path)534 hidden_def(selinux_file_context_subs_path)
535
536 const char * selinux_file_context_subs_dist_path(void) {
537 return get_path(FILE_CONTEXT_SUBS_DIST);
538 }
539
hidden_def(selinux_file_context_subs_dist_path)540 hidden_def(selinux_file_context_subs_dist_path)
541
542 const char *selinux_sepgsql_context_path(void)
543 {
544 return get_path(SEPGSQL_CONTEXTS);
545 }
546
547 hidden_def(selinux_sepgsql_context_path)
548