1 #include <unistd.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <pwd.h>
8 #include <limits.h>
9 #include "selinux_internal.h"
10 #include "context_internal.h"
11
12 static char **customizable_list = NULL;
13 static pthread_once_t customizable_once = PTHREAD_ONCE_INIT;
14
customizable_init(void)15 static void customizable_init(void)
16 {
17 FILE *fp;
18 char *buf;
19 unsigned int ctr = 0, i;
20 char **list = NULL;
21
22 fp = fopen(selinux_customizable_types_path(), "re");
23 if (!fp)
24 return;
25
26 buf = malloc(selinux_page_size);
27 if (!buf) {
28 fclose(fp);
29 return;
30 }
31 while (fgets_unlocked(buf, selinux_page_size, fp) && ctr < UINT_MAX) {
32 ctr++;
33 }
34
35 if (fseek(fp, 0L, SEEK_SET) == -1) {
36 free(buf);
37 fclose(fp);
38 return;
39 }
40
41 if (ctr) {
42 list = calloc(ctr + 1, sizeof(char *));
43 if (list) {
44 i = 0;
45 while (fgets_unlocked(buf, selinux_page_size, fp)
46 && i < ctr) {
47 buf[strlen(buf) - 1] = 0;
48 list[i] = strdup(buf);
49 if (!list[i]) {
50 unsigned int j;
51 for (j = 0; j < i; j++)
52 free(list[j]);
53 free(list);
54 list = NULL;
55 break;
56 }
57 i++;
58 }
59 }
60 }
61 fclose(fp);
62 free(buf);
63 if (!list)
64 return;
65 customizable_list = list;
66 }
67
is_context_customizable(const char * scontext)68 int is_context_customizable(const char * scontext)
69 {
70 int i;
71 const char *type;
72 context_t c;
73
74 __selinux_once(customizable_once, customizable_init);
75 if (!customizable_list)
76 return -1;
77
78 c = context_new(scontext);
79 if (!c)
80 return -1;
81
82 type = context_type_get(c);
83 if (!type) {
84 context_free(c);
85 return -1;
86 }
87
88 for (i = 0; customizable_list[i]; i++) {
89 if (strcmp(customizable_list[i], type) == 0) {
90 context_free(c);
91 return 1;
92 }
93 }
94 context_free(c);
95 return 0;
96 }
97