blob: 30e9dc74a97bb9ed6d1a53d393e270aea8809918 [file] [log] [blame]
Joshua Brindle13cd4c82008-08-19 15:30:36 -04001#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>
Stephen Smalley8c372f62009-07-01 13:45:40 -040010#include <pthread.h>
Dan Walsh7fe60362013-10-09 14:46:05 -040011#include <errno.h>
12#include "policy.h"
Joshua Brindle13cd4c82008-08-19 15:30:36 -040013#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
Eamon Walshf9b1f1a2008-12-31 18:55:20 -050045#define COLORS 20
Daniel J Walsh20271d92009-06-04 17:15:31 -040046#define VIRTUAL_DOMAIN 21
47#define VIRTUAL_IMAGE 22
48#define FILE_CONTEXT_SUBS 23
Eamon Walsh70aeeb92010-03-15 18:38:35 -040049#define SEPGSQL_CONTEXTS 24
Daniel J Walsh20b43b32011-04-06 17:08:27 -040050#define FILE_CONTEXT_SUBS_DIST 25
Dan Walshc802d4a2012-04-18 14:46:12 -040051#define LXC_CONTEXTS 26
Eric Paris88c35242012-04-18 11:00:24 -040052#define BOOLEAN_SUBS 27
Dan Walshce2a8842013-10-09 14:52:49 -040053#define SYSTEMD_CONTEXTS 28
54#define NEL 29
Joshua Brindle13cd4c82008-08-19 15:30:36 -040055
Stephen Smalley8c372f62009-07-01 13:45:40 -040056/* Part of one-time lazy init */
57static pthread_once_t once = PTHREAD_ONCE_INIT;
58static void init_selinux_config(void);
59
Joshua Brindle13cd4c82008-08-19 15:30:36 -040060/* New layout is relative to SELINUXDIR/policytype. */
61static char *file_paths[NEL];
62#define L1(l) L2(l)
63#define L2(l)str##l
64static 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};
78static 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
87int 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
129hidden_def(selinux_getenforcemode)
130
131static char *selinux_policytype;
132
133int selinux_getpolicytype(char **type)
134{
Stephen Smalley8c372f62009-07-01 13:45:40 -0400135 __selinux_once(once, init_selinux_config);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400136 if (!selinux_policytype)
137 return -1;
138 *type = strdup(selinux_policytype);
139 return *type ? 0 : -1;
140}
141
142hidden_def(selinux_getpolicytype)
143
Dan Walsh7fe60362013-10-09 14:46:05 -0400144static int setpolicytype(const char *type)
145{
146 free(selinux_policytype);
147 selinux_policytype = strdup(type);
148 return selinux_policytype ? 0 : -1;
149}
150
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400151static char *selinux_policyroot = NULL;
Stephen Smalley8c372f62009-07-01 13:45:40 -0400152static const char *selinux_rootpath = SELINUXDIR;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400153
154static 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
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400165 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
232static void fini_selinux_policyroot(void) __attribute__ ((destructor));
233
234static 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
Chad Sellers7d19f9d2009-10-20 11:21:59 -0400247void selinux_reset_config(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400248{
249 fini_selinux_policyroot();
250 init_selinux_config();
251}
252
Chad Sellers7d19f9d2009-10-20 11:21:59 -0400253hidden_def(selinux_reset_config)
254
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400255static const char *get_path(int idx)
256{
Stephen Smalley8c372f62009-07-01 13:45:40 -0400257 __selinux_once(once, init_selinux_config);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400258 return file_paths[idx];
259}
260
Daniel P. Berrange86795152012-01-23 15:41:13 +0000261const char *selinux_default_type_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400262{
263 return get_path(DEFAULT_TYPE);
264}
265
266hidden_def(selinux_default_type_path)
267
Daniel P. Berrange86795152012-01-23 15:41:13 +0000268const char *selinux_policy_root(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400269{
Stephen Smalley8c372f62009-07-01 13:45:40 -0400270 __selinux_once(once, init_selinux_config);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400271 return selinux_policyroot;
272}
273
Dan Walsh7fe60362013-10-09 14:46:05 -0400274int 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
Daniel P. Berrange86795152012-01-23 15:41:13 +0000305const char *selinux_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400306{
307 return selinux_rootpath;
308}
309
310hidden_def(selinux_path)
311
Daniel P. Berrange86795152012-01-23 15:41:13 +0000312const char *selinux_default_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400313{
314 return get_path(DEFAULT_CONTEXTS);
315}
316
317hidden_def(selinux_default_context_path)
318
Daniel P. Berrange86795152012-01-23 15:41:13 +0000319const char *selinux_securetty_types_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400320{
321 return get_path(SECURETTY_TYPES);
322}
323
324hidden_def(selinux_securetty_types_path)
325
Daniel P. Berrange86795152012-01-23 15:41:13 +0000326const char *selinux_failsafe_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400327{
328 return get_path(FAILSAFE_CONTEXT);
329}
330
331hidden_def(selinux_failsafe_context_path)
332
Daniel P. Berrange86795152012-01-23 15:41:13 +0000333const char *selinux_removable_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400334{
335 return get_path(REMOVABLE_CONTEXT);
336}
337
338hidden_def(selinux_removable_context_path)
339
Daniel P. Berrange86795152012-01-23 15:41:13 +0000340const char *selinux_binary_policy_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400341{
342 return get_path(BINPOLICY);
343}
344
345hidden_def(selinux_binary_policy_path)
346
Dan Walsh7eec00a2013-10-09 16:18:15 -0400347const 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
370hidden_def(selinux_current_policy_path)
371
Daniel P. Berrange86795152012-01-23 15:41:13 +0000372const char *selinux_file_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400373{
374 return get_path(FILE_CONTEXTS);
375}
376
377hidden_def(selinux_file_context_path)
378
Daniel P. Berrange86795152012-01-23 15:41:13 +0000379const char *selinux_homedir_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400380{
381 return get_path(HOMEDIR_CONTEXTS);
382}
383
384hidden_def(selinux_homedir_context_path)
385
Daniel P. Berrange86795152012-01-23 15:41:13 +0000386const char *selinux_media_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400387{
388 return get_path(MEDIA_CONTEXTS);
389}
390
391hidden_def(selinux_media_context_path)
392
Daniel P. Berrange86795152012-01-23 15:41:13 +0000393const char *selinux_customizable_types_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400394{
395 return get_path(CUSTOMIZABLE_TYPES);
396}
397
398hidden_def(selinux_customizable_types_path)
399
Daniel P. Berrange86795152012-01-23 15:41:13 +0000400const char *selinux_contexts_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400401{
402 return get_path(CONTEXTS_DIR);
403}
404
Daniel P. Berrange86795152012-01-23 15:41:13 +0000405const char *selinux_user_contexts_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400406{
407 return get_path(USER_CONTEXTS);
408}
409
410hidden_def(selinux_user_contexts_path)
411
Daniel P. Berrange86795152012-01-23 15:41:13 +0000412const char *selinux_booleans_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400413{
414 return get_path(BOOLEANS);
415}
416
417hidden_def(selinux_booleans_path)
418
Daniel P. Berrange86795152012-01-23 15:41:13 +0000419const char *selinux_users_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400420{
421 return get_path(USERS_DIR);
422}
423
424hidden_def(selinux_users_path)
425
Daniel P. Berrange86795152012-01-23 15:41:13 +0000426const char *selinux_usersconf_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400427{
428 return get_path(SEUSERS);
429}
430
431hidden_def(selinux_usersconf_path)
432
Daniel P. Berrange86795152012-01-23 15:41:13 +0000433const char *selinux_translations_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400434{
435 return get_path(TRANSLATIONS);
436}
437
438hidden_def(selinux_translations_path)
439
Daniel P. Berrange86795152012-01-23 15:41:13 +0000440const char *selinux_colors_path(void)
Eamon Walshf9b1f1a2008-12-31 18:55:20 -0500441{
442 return get_path(COLORS);
443}
444
445hidden_def(selinux_colors_path)
446
Daniel P. Berrange86795152012-01-23 15:41:13 +0000447const char *selinux_netfilter_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400448{
449 return get_path(NETFILTER_CONTEXTS);
450}
451
452hidden_def(selinux_netfilter_context_path)
453
Daniel P. Berrange86795152012-01-23 15:41:13 +0000454const char *selinux_file_context_homedir_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400455{
456 return get_path(FILE_CONTEXTS_HOMEDIR);
457}
458
459hidden_def(selinux_file_context_homedir_path)
460
Daniel P. Berrange86795152012-01-23 15:41:13 +0000461const char *selinux_file_context_local_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400462{
463 return get_path(FILE_CONTEXTS_LOCAL);
464}
465
466hidden_def(selinux_file_context_local_path)
467
Daniel P. Berrange86795152012-01-23 15:41:13 +0000468const char *selinux_x_context_path(void)
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400469{
470 return get_path(X_CONTEXTS);
471}
472
473hidden_def(selinux_x_context_path)
Daniel J Walsh20271d92009-06-04 17:15:31 -0400474
Daniel P. Berrange86795152012-01-23 15:41:13 +0000475const char *selinux_virtual_domain_context_path(void)
Daniel J Walsh20271d92009-06-04 17:15:31 -0400476{
477 return get_path(VIRTUAL_DOMAIN);
478}
479
480hidden_def(selinux_virtual_domain_context_path)
481
Daniel P. Berrange86795152012-01-23 15:41:13 +0000482const char *selinux_virtual_image_context_path(void)
Daniel J Walsh20271d92009-06-04 17:15:31 -0400483{
484 return get_path(VIRTUAL_IMAGE);
485}
486
487hidden_def(selinux_virtual_image_context_path)
488
Dan Walshc802d4a2012-04-18 14:46:12 -0400489const char *selinux_lxc_contexts_path(void)
490{
491 return get_path(LXC_CONTEXTS);
492}
493
494hidden_def(selinux_lxc_contexts_path)
495
Dan Walshce2a8842013-10-09 14:52:49 -0400496const char *selinux_systemd_contexts_path(void)
497{
498 return get_path(SYSTEMD_CONTEXTS);
499}
500
501hidden_def(selinux_systemd_contexts_path)
502
Eric Paris88c35242012-04-18 11:00:24 -0400503const char * selinux_booleans_subs_path(void) {
504 return get_path(BOOLEAN_SUBS);
505}
506
507hidden_def(selinux_booleans_subs_path)
508
Daniel J Walsh20271d92009-06-04 17:15:31 -0400509const char * selinux_file_context_subs_path(void) {
510 return get_path(FILE_CONTEXT_SUBS);
511}
512
513hidden_def(selinux_file_context_subs_path)
514
Daniel J Walsh20b43b32011-04-06 17:08:27 -0400515const char * selinux_file_context_subs_dist_path(void) {
516 return get_path(FILE_CONTEXT_SUBS_DIST);
517}
518
519hidden_def(selinux_file_context_subs_dist_path)
520
Daniel P. Berrange86795152012-01-23 15:41:13 +0000521const char *selinux_sepgsql_context_path(void)
Eamon Walsh70aeeb92010-03-15 18:38:35 -0400522{
523 return get_path(SEPGSQL_CONTEXTS);
524}
525
526hidden_def(selinux_sepgsql_context_path)